diff options
| -rw-r--r-- | xlators/mgmt/glusterd/src/Makefile.am | 8 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-brick-ops.c | 920 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-geo-rep.c | 1579 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 1323 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-log-ops.c | 804 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 5546 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-quota.c | 810 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-replace-brick.c | 1929 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 1038 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 53 | 
10 files changed, 7140 insertions, 6870 deletions
diff --git a/xlators/mgmt/glusterd/src/Makefile.am b/xlators/mgmt/glusterd/src/Makefile.am index 714b78e62..01fbbd064 100644 --- a/xlators/mgmt/glusterd/src/Makefile.am +++ b/xlators/mgmt/glusterd/src/Makefile.am @@ -3,10 +3,12 @@ xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/mgmt  glusterd_la_LDFLAGS = -module -avoidversion $(LIBXML2_LIBS)  glusterd_la_SOURCES = glusterd.c glusterd-handler.c glusterd-sm.c glusterd-op-sm.c \  	glusterd-utils.c glusterd-rpc-ops.c glusterd-store.c glusterd-handshake.c \ -	glusterd-pmap.c glusterd-volgen.c glusterd-rebalance.c +	glusterd-pmap.c glusterd-volgen.c glusterd-rebalance.c glusterd-quota.c \ +	glusterd-geo-rep.c glusterd-replace-brick.c glusterd-log-ops.c \ +	glusterd-volume-ops.c glusterd-brick-ops.c -glusterd_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la\ -		     $(top_builddir)/rpc/xdr/src/libgfxdr.la\ +glusterd_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \ +		     $(top_builddir)/rpc/xdr/src/libgfxdr.la \  		     $(top_builddir)/rpc/rpc-lib/src/libgfrpc.la  noinst_HEADERS = glusterd.h glusterd-utils.h glusterd-op-sm.h glusterd-sm.h \ diff --git a/xlators/mgmt/glusterd/src/glusterd-brick-ops.c b/xlators/mgmt/glusterd/src/glusterd-brick-ops.c new file mode 100644 index 000000000..d05dd49a1 --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-brick-ops.c @@ -0,0 +1,920 @@ +/* +  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/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "cli1.h" +#include "glusterd.h" +#include "glusterd-op-sm.h" +#include "glusterd-store.h" +#include "glusterd-utils.h" +#include "glusterd-volgen.h" +#include "run.h" + +int +glusterd_handle_add_brick (rpcsvc_request_t *req) +{ +        int32_t                         ret = -1; +        gf1_cli_add_brick_req          cli_req = {0,}; +        dict_t                          *dict = NULL; +        glusterd_brickinfo_t            *brickinfo = NULL; +        char                            *brick = NULL; +        char                            *bricks = NULL; +        char                            *volname = NULL; +        int                             brick_count = 0; +        char                            *tmpptr = NULL; +        int                             i = 0; +        char                            *brick_list = NULL; +        void                            *cli_rsp = NULL; +        char                            err_str[2048] = {0,}; +        gf1_cli_add_brick_rsp           rsp = {0,}; +        glusterd_volinfo_t              *volinfo = NULL; +        glusterd_conf_t                 *priv = NULL; +        xlator_t                        *this = NULL; +        char                            *free_ptr = NULL; +        glusterd_brickinfo_t            *tmpbrkinfo = NULL; +        glusterd_volinfo_t              tmpvolinfo = {{0},}; +        int                             total_bricks = 0; + +        this = THIS; +        GF_ASSERT(this); + +        priv = this->private; + +        GF_ASSERT (req); + +        INIT_LIST_HEAD (&tmpvolinfo.bricks); + +        if (!gf_xdr_to_cli_add_brick_req (req->msg[0], &cli_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                snprintf (err_str, sizeof (err_str), "Garbage args received"); +                goto out; +        } + +        gf_cmd_log ("Volume add-brick", "on volname: %s attempted", +                    cli_req.volname); +        gf_log ("glusterd", GF_LOG_INFO, "Received add brick req"); + +        if (cli_req.bricks.bricks_len) { +                /* Unserialize the dictionary */ +                dict  = dict_new (); + +                ret = dict_unserialize (cli_req.bricks.bricks_val, +                                        cli_req.bricks.bricks_len, +                                        &dict); +                if (ret < 0) { +                        gf_log ("glusterd", GF_LOG_ERROR, +                                "failed to " +                                "unserialize req-buffer to dictionary"); +                        snprintf (err_str, sizeof (err_str), "Unable to decode " +                                  "the buffer"); +                        goto out; +                } else { +                        dict->extra_stdfree = cli_req.bricks.bricks_val; +                } +        } + +        ret = dict_get_str (dict, "volname", &volname); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                snprintf (err_str, sizeof (err_str), "Unable to get volume " +                          "name"); +                goto out; +        } + +        if (!(ret = glusterd_check_volume_exists (volname))) { +                ret = -1; +                snprintf(err_str, 2048, "Volume %s does not exist", volname); +                gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); +                goto out; +        } + +        ret = dict_get_int32 (dict, "count", &brick_count); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get count"); +                snprintf (err_str, sizeof (err_str), "Unable to get volume " +                          "brick count"); +                goto out; +        } + +        if (!(ret = glusterd_volinfo_find (volname, &volinfo))) { +                if (volinfo->type == GF_CLUSTER_TYPE_NONE) +                        goto brick_val; +                if (!brick_count || !volinfo->sub_count) +                        goto brick_val; + +                total_bricks = volinfo->brick_count + brick_count; +		/* If the brick count is less than sub_count then, allow add-brick only for +		   plain replicate volume since in plain stripe brick_count becoming less than +		   the sub_count is not allowed */ +                if (volinfo->brick_count < volinfo->sub_count && +                    (volinfo->type == GF_CLUSTER_TYPE_REPLICATE)) { +                        if (total_bricks <= volinfo->sub_count) +                                goto brick_val; +                } + +                if ((brick_count % volinfo->sub_count) != 0) { +                        snprintf(err_str, 2048, "Incorrect number of bricks" +                                " supplied %d for type %s with count %d", +                                brick_count, (volinfo->type == 1)? "STRIPE": +                                "REPLICATE", volinfo->sub_count); +                        gf_log("glusterd", GF_LOG_ERROR, "%s", err_str); +                        ret = -1; +                        goto out; +                } +        } else { +                snprintf (err_str, sizeof (err_str), "Unable to get volinfo " +                          "for volume name %s", volname); +                gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); +                goto out; +        } + +brick_val: +        ret = dict_get_str (dict, "bricks", &bricks); +        if (ret) { +                snprintf (err_str, sizeof (err_str), "Unable to get volume " +                          "bricks"); +                gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); +                goto out; +        } + +        if (bricks) +                brick_list = gf_strdup (bricks); +        if (!brick_list) { +                ret = -1; +                snprintf (err_str, sizeof (err_str), "Out of memory"); +                goto out; +        } else { +                free_ptr = brick_list; +        } + +        gf_cmd_log ("Volume add-brick", "volname: %s type %s count:%d bricks:%s" +                    ,volname, ((volinfo->type == 0)? "DEFAULT" : ((volinfo->type +                    == 1)? "STRIPE": "REPLICATE")), brick_count, brick_list); + + +        while ( i < brick_count) { +                i++; +                brick= strtok_r (brick_list, " \n", &tmpptr); +                brick_list = tmpptr; +                brickinfo = NULL; +                ret = glusterd_brickinfo_from_brick (brick, &brickinfo); +                if (ret) { +                        snprintf (err_str, sizeof (err_str), "Unable to get " +                                  "brick info from brick %s", brick); +                        goto out; +                } +                ret = glusterd_new_brick_validate (brick, brickinfo, err_str, +                                                   sizeof (err_str)); +                if (ret) +                        goto out; +                ret = glusterd_volume_brickinfo_get (brickinfo->uuid, +                                                     brickinfo->hostname, +                                                     brickinfo->path, +                                                     &tmpvolinfo, &tmpbrkinfo); +                if (!ret) { +                        ret = -1; +                        snprintf (err_str, sizeof (err_str), "Brick: %s:%s, %s" +                                  " one of the arguments contain the other", +                                  tmpbrkinfo->hostname, tmpbrkinfo->path, brick); +                        goto out; +                } +                list_add_tail (&brickinfo->brick_list, &tmpvolinfo.bricks); +                brickinfo = NULL; +        } + +        ret = glusterd_op_begin (req, GD_OP_ADD_BRICK, dict); +        gf_cmd_log ("Volume add-brick","on volname: %s %s", volname, +                   (ret != 0)? "FAILED" : "SUCCESS"); + +out: +        if (ret) { +                if (dict) +                        dict_unref (dict); +                rsp.op_ret = -1; +                rsp.op_errno = 0; +                rsp.volname = ""; +                if (err_str[0] == '\0') +                        snprintf (err_str, sizeof (err_str), "Operation failed"); +                rsp.op_errstr = err_str; +                cli_rsp = &rsp; +                glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL, +                                      gf_xdr_serialize_cli_add_brick_rsp, +                                      (xdrproc_t)xdr_gf1_cli_add_brick_rsp); +                ret = 0; //sent error to cli, prevent second reply +        } + +        glusterd_friend_sm (); +        glusterd_op_sm (); + +        if (free_ptr) +                GF_FREE (free_ptr); +        glusterd_volume_brickinfos_delete (&tmpvolinfo); +        if (brickinfo) +                glusterd_brickinfo_delete (brickinfo); +        if (cli_req.volname) +                free (cli_req.volname); //its malloced by xdr + +        return ret; +} + +int +glusterd_handle_remove_brick (rpcsvc_request_t *req) +{ +        int32_t                         ret = -1; +        gf1_cli_remove_brick_req        cli_req = {0,}; +        dict_t                          *dict = NULL; +        int32_t                         count = 0; +        char                            *brick = NULL; +        char                            key[256] = {0,}; +        char                            *brick_list = NULL; +        int                             i = 1; +        glusterd_volinfo_t              *volinfo = NULL; +        glusterd_brickinfo_t            *brickinfo = NULL; +        int32_t                         pos = 0; +        int32_t                         sub_volume = 0; +        int32_t                         sub_volume_start = 0; +        int32_t                         sub_volume_end = 0; +        glusterd_brickinfo_t            *tmp = NULL; +        char                            err_str[2048] = {0}; +        gf1_cli_remove_brick_rsp        rsp = {0,}; +        void                            *cli_rsp = NULL; +        char                            vol_type[256] = {0,}; + +        GF_ASSERT (req); + +        if (!gf_xdr_to_cli_remove_brick_req (req->msg[0], &cli_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        gf_cmd_log ("Volume remove-brick","on volname: %s attempted",cli_req.volname); +        gf_log ("glusterd", GF_LOG_INFO, "Received rem brick req"); + +        if (cli_req.bricks.bricks_len) { +                /* Unserialize the dictionary */ +                dict  = dict_new (); + +                ret = dict_unserialize (cli_req.bricks.bricks_val, +                                        cli_req.bricks.bricks_len, +                                        &dict); +                if (ret < 0) { +                        gf_log ("glusterd", GF_LOG_ERROR, +                                "failed to " +                                "unserialize req-buffer to dictionary"); +                        goto out; +                } else { +                        dict->extra_stdfree = cli_req.bricks.bricks_val; +                } +        } + +        ret = dict_get_int32 (dict, "count", &count); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get count"); +                goto out; +        } + +        ret = glusterd_volinfo_find (cli_req.volname, &volinfo); +        if (ret) { +                 snprintf (err_str, 2048, "Volume %s does not exist", +                          cli_req.volname); +                 gf_log ("", GF_LOG_ERROR, "%s", err_str); +                 goto out; +        } + +        if (volinfo->type == GF_CLUSTER_TYPE_REPLICATE) +                strcpy (vol_type, "replica"); +        else if (volinfo->type == GF_CLUSTER_TYPE_STRIPE) +                strcpy (vol_type, "stripe"); +        else +                strcpy (vol_type, "distribute"); + +	/* Do not allow remove-brick if the volume is plain stripe */ +	if ((volinfo->type == GF_CLUSTER_TYPE_STRIPE) && (volinfo->brick_count == volinfo->sub_count)) { +                snprintf (err_str, 2048, "Removing brick from a plain stripe is not allowed"); +                gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); +                ret = -1; +                goto out; +	} + +	/* Do not allow remove-brick if the bricks given is less than the replica count +	   or stripe count */ +        if (((volinfo->type == GF_CLUSTER_TYPE_REPLICATE) || (volinfo->type == GF_CLUSTER_TYPE_STRIPE)) +	    && !(volinfo->brick_count <= volinfo->sub_count)) { +                if (volinfo->sub_count && (count % volinfo->sub_count != 0)) { +                        snprintf (err_str, 2048, "Remove brick incorrect" +                                  " brick count of %d for %s %d", +                                  count, vol_type, volinfo->sub_count); +                        gf_log ("", GF_LOG_ERROR, "%s", err_str); +                        ret = -1; +                        goto out; +                } +        } + +        brick_list = GF_MALLOC (120000 * sizeof(*brick_list),gf_common_mt_char); + +        if (!brick_list) { +                ret = -1; +                goto out; +        } + +        strcpy (brick_list, " "); +        while ( i <= count) { +                snprintf (key, 256, "brick%d", i); +                ret = dict_get_str (dict, key, &brick); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, "Unable to get %s", key); +                        goto out; +                } +                gf_log ("", GF_LOG_DEBUG, "Remove brick count %d brick: %s", +                        i, brick); + +                ret = glusterd_volume_brickinfo_get_by_brick(brick, volinfo, &brickinfo); +                if (ret) { +                        snprintf(err_str, 2048,"Incorrect brick %s for volume" +                                " %s", brick, cli_req.volname); +                        gf_log ("", GF_LOG_ERROR, "%s", err_str); +                        goto out; +                } +                strcat(brick_list, brick); +                strcat(brick_list, " "); + +                i++; +                if ((volinfo->type == GF_CLUSTER_TYPE_NONE) || +                    (volinfo->brick_count <= volinfo->sub_count)) +                        continue; + +                pos = 0; +                list_for_each_entry (tmp, &volinfo->bricks, brick_list) { + +                        if ((!strcmp (tmp->hostname,brickinfo->hostname)) && +                            !strcmp (tmp->path, brickinfo->path)) { +                                gf_log ("", GF_LOG_INFO, "Found brick"); +                                if (!sub_volume && volinfo->sub_count) { +                                        sub_volume = (pos / volinfo-> +                                                      sub_count) + 1; +                                        sub_volume_start = volinfo->sub_count * +                                                           (sub_volume - 1); +                                        sub_volume_end = (volinfo->sub_count * +                                                          sub_volume) -1 ; +                                } else { +                                        if (pos < sub_volume_start || +                                            pos >sub_volume_end) { +                                                ret = -1; +                                                snprintf(err_str, 2048,"Bricks" +                                                         " not from same subvol" +                                                         " for %s", vol_type); +                                                gf_log ("",GF_LOG_ERROR, +                                                        "%s", err_str); +                                                goto out; +                                        } +                                } +                                break; +                        } +                        pos++; +                } +        } +        gf_cmd_log ("Volume remove-brick","volname: %s count:%d bricks:%s", +                    cli_req.volname, count, brick_list); + +        ret = glusterd_op_begin (req, GD_OP_REMOVE_BRICK, dict); +        gf_cmd_log ("Volume remove-brick","on volname: %s %s",cli_req.volname, +                    (ret) ? "FAILED" : "SUCCESS"); + +out: +        if (ret) { +                if (dict) +                        dict_unref (dict); +                rsp.op_ret = -1; +                rsp.op_errno = 0; +                rsp.volname = ""; +                if (err_str[0] == '\0') +                        snprintf (err_str, sizeof (err_str), "Operation failed"); +                gf_log ("", GF_LOG_ERROR, "%s", err_str); +                rsp.op_errstr = err_str; +                cli_rsp = &rsp; +                glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL, +                                      gf_xdr_serialize_cli_remove_brick_rsp, +                                      (xdrproc_t)xdr_gf1_cli_remove_brick_rsp); + +                ret = 0; //sent error to cli, prevent second reply + +        } +        if (brick_list) +                GF_FREE (brick_list); +        if (cli_req.volname) +                free (cli_req.volname); //its malloced by xdr + +        glusterd_friend_sm (); +        glusterd_op_sm (); + +        return ret; +} + + +/* op-sm */ + +int +glusterd_op_perform_add_bricks (glusterd_volinfo_t  *volinfo, int32_t count, +                                char  *bricks) +{ +        glusterd_brickinfo_t                    *brickinfo = NULL; +        char                                    *brick = NULL; +        int32_t                                 i = 1; +        char                                    *brick_list = NULL; +        char                                    *free_ptr1  = NULL; +        char                                    *free_ptr2  = NULL; +        char                                    *saveptr = NULL; +        int32_t                                 ret = -1; +        glusterd_conf_t                         *priv = NULL; + +        priv = THIS->private; + +        GF_ASSERT (volinfo); + +        if (bricks) { +                brick_list = gf_strdup (bricks); +                free_ptr1 = brick_list; +        } + +        if (count) +                brick = strtok_r (brick_list+1, " \n", &saveptr); + +        while ( i <= count) { +                ret = glusterd_brickinfo_from_brick (brick, &brickinfo); +                if (ret) +                        goto out; + +                ret = glusterd_resolve_brick (brickinfo); +                if (ret) +                        goto out; +                list_add_tail (&brickinfo->brick_list, &volinfo->bricks); +                brick = strtok_r (NULL, " \n", &saveptr); +                i++; +                volinfo->brick_count++; + +        } + +        brick_list = gf_strdup (bricks); +        free_ptr2 = brick_list; +        i = 1; + +        if (count) +                brick = strtok_r (brick_list+1, " \n", &saveptr); + +        ret = glusterd_create_volfiles_and_notify_services (volinfo); +        if (ret) +                goto out; + +        while (i <= count) { + +                ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, +                                                              &brickinfo); +                if (ret) +                        goto out; + +                if (GLUSTERD_STATUS_STARTED == volinfo->status) { +                        ret = glusterd_brick_start (volinfo, brickinfo); +                        if (ret) +                                goto out; +                } +                i++; +                brick = strtok_r (NULL, " \n", &saveptr); +        } + +out: +        if (free_ptr1) +                GF_FREE (free_ptr1); +        if (free_ptr2) +                GF_FREE (free_ptr2); + +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + + +int +glusterd_op_perform_remove_brick (glusterd_volinfo_t  *volinfo, char *brick) +{ + +        glusterd_brickinfo_t    *brickinfo = NULL; +        char                    *dup_brick = NULL; +        glusterd_conf_t         *priv = NULL; +        int32_t                 ret = -1; + +        GF_ASSERT (volinfo); +        GF_ASSERT (brick); + +        priv = THIS->private; + +        dup_brick = gf_strdup (brick); +        if (!dup_brick) +                goto out; + +        ret = glusterd_volume_brickinfo_get_by_brick (dup_brick, volinfo,  &brickinfo); +        if (ret) +                goto out; + +        ret = glusterd_resolve_brick (brickinfo); +        if (ret) +                goto out; + +        if (GLUSTERD_STATUS_STARTED == volinfo->status) { +                ret = glusterd_brick_stop (volinfo, brickinfo); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, "Unable to stop " +                                "glusterfs, ret: %d", ret); +                        goto out; +                } +        } +        glusterd_delete_brick (volinfo, brickinfo); +out: +        if (dup_brick) +                GF_FREE (dup_brick); + +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +glusterd_op_stage_add_brick (dict_t *dict, char **op_errstr) +{ +        int                                     ret = 0; +        char                                    *volname = NULL; +        int                                     count = 0; +        int                                     i = 0; +        char                                    *bricks    = NULL; +        char                                    *brick_list = NULL; +        char                                    *saveptr = NULL; +        char                                    *free_ptr = NULL; +        char                                    *brick = NULL; +        glusterd_brickinfo_t                    *brickinfo = NULL; +        glusterd_volinfo_t                      *volinfo = NULL; +        char                                    cmd_str[1024]; +        glusterd_conf_t                         *priv = NULL; +        char                                    msg[2048] = {0,}; +        gf_boolean_t                            brick_alloc = _gf_false; +        char                                    *all_bricks = NULL; +        char                                    *str_ret = NULL; + +        priv = THIS->private; +        if (!priv) +                goto out; + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to find volume: %s", volname); +                goto out; +        } + +        if (glusterd_is_defrag_on(volinfo)) { +                snprintf (msg, sizeof(msg), "Volume name %s rebalance is in " +                          "progress. Please retry after completion", volname); +                gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); +                *op_errstr = gf_strdup (msg); +                ret = -1; +                goto out; +        } +        ret = dict_get_int32 (dict, "count", &count); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get count"); +                goto out; +        } + +        ret = dict_get_str (dict, "bricks", &bricks); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); +                goto out; +        } + +        if (bricks) { +                brick_list = gf_strdup (bricks); +                all_bricks = gf_strdup (bricks); +                free_ptr = brick_list; +        } + +        /* Check whether any of the bricks given is the destination brick of the +           replace brick running */ + +        str_ret = glusterd_check_brick_rb_part (all_bricks, count, volinfo); +        if (str_ret) { +                gf_log ("glusterd", GF_LOG_ERROR, +                        "%s", str_ret); +                *op_errstr = gf_strdup (str_ret); +                ret = -1; +                goto out; +        } + +        if (count) +                brick = strtok_r (brick_list+1, " \n", &saveptr); + + +        while ( i < count) { +                if (!glusterd_store_is_valid_brickpath (volname, brick) || +                        !glusterd_is_valid_volfpath (volname, brick)) { +                        snprintf (msg, sizeof (msg), "brick path %s is too " +                                  "long.", brick); +                        gf_log ("", GF_LOG_ERROR, "%s", msg); +                        *op_errstr = gf_strdup (msg); + +                        ret = -1; +                        goto out; + +                } + +                ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, +                                                              &brickinfo); +                if (!ret) { +                        gf_log ("", GF_LOG_ERROR, "Adding duplicate brick: %s", +                                brick); +                        ret = -1; +                        goto out; +                } else { +                        ret = glusterd_brickinfo_from_brick (brick, &brickinfo); +                        if (ret) { +                                gf_log ("", GF_LOG_ERROR, "Add-brick: Unable" +                                        " to get brickinfo"); +                                goto out; +                        } +                        brick_alloc = _gf_true; +                } + +                snprintf (cmd_str, 1024, "%s", brickinfo->path); +                ret = glusterd_resolve_brick (brickinfo); +                if (ret) { +                        gf_log ("glusterd", GF_LOG_ERROR, +                                "resolve brick failed"); +                        goto out; +                } + +                if (!uuid_compare (brickinfo->uuid, priv->uuid)) { +                        ret = glusterd_brick_create_path (brickinfo->hostname, +                                                          brickinfo->path, +                                                          volinfo->volume_id, +                                                          0777, op_errstr); +                        if (ret) +                                goto out; +                } + +                glusterd_brickinfo_delete (brickinfo); +                brick_alloc = _gf_false; +                brickinfo = NULL; +                brick = strtok_r (NULL, " \n", &saveptr); +                i++; +        } + +out: +        if (free_ptr) +                GF_FREE (free_ptr); +        if (brick_alloc && brickinfo) +                glusterd_brickinfo_delete (brickinfo); +        if (str_ret) +                GF_FREE (str_ret); +        if (all_bricks) +                GF_FREE (all_bricks); + +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +        return ret; +} + +int +glusterd_op_stage_remove_brick (dict_t *dict) +{ +        int                                     ret = -1; +        char                                    *volname = NULL; +        glusterd_volinfo_t                      *volinfo = NULL; +        dict_t                                  *ctx     = NULL; +        char                                    *errstr  = NULL; +        int32_t                                 brick_count = 0; + +        ret = dict_get_str (dict, "volname", &volname); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        ret = glusterd_volinfo_find (volname, &volinfo); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Volume %s does not exist", volname); +                goto out; +        } + +        if (glusterd_is_defrag_on(volinfo)) { +                ctx = glusterd_op_get_ctx (); +                errstr = gf_strdup("Rebalance is in progress. Please retry" +                                    " after completion"); +                if (!errstr) { +                        ret = -1; +                        goto out; +                } +                gf_log ("glusterd", GF_LOG_ERROR, "%s", errstr); +                ret = dict_set_dynstr (ctx, "errstr", errstr); +                if (ret) { +                        GF_FREE (errstr); +                        gf_log ("", GF_LOG_DEBUG, +                                "failed to set errstr ctx"); +                        goto out; +                } + +                ret = -1; +                goto out; +        } + +        ret = dict_get_int32 (dict, "count", &brick_count); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get brick count"); +                goto out; +        } + +        if (volinfo->brick_count == brick_count) { +                ctx = glusterd_op_get_ctx (); +                if (!ctx) { +                        gf_log ("", GF_LOG_ERROR, +                                "Operation Context is not present"); +                        ret = -1; +                        goto out; +                } +                errstr = gf_strdup ("Deleting all the bricks of the " +                                    "volume is not allowed"); +                if (!errstr) { +                        gf_log ("", GF_LOG_ERROR, "Out of memory"); +                        ret = -1; +                        goto out; +                } + +                ret = dict_set_dynstr (ctx, "errstr", errstr); +                if (ret) { +                        GF_FREE (errstr); +                        gf_log ("", GF_LOG_DEBUG, +                                "failed to set pump status in ctx"); +                        goto out; +                } + +                ret = -1; +                goto out; +        } + +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +        return ret; +} + +int +glusterd_op_add_brick (dict_t *dict, char **op_errstr) +{ +        int                                     ret = 0; +        char                                    *volname = NULL; +        glusterd_conf_t                         *priv = NULL; +        glusterd_volinfo_t                      *volinfo = NULL; +        xlator_t                                *this = NULL; +        char                                    *bricks = NULL; +        int32_t                                 count = 0; + +        this = THIS; +        GF_ASSERT (this); + +        priv = this->private; +        GF_ASSERT (priv); + +        ret = dict_get_str (dict, "volname", &volname); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        ret = glusterd_volinfo_find (volname, &volinfo); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); +                goto out; +        } + +        ret = dict_get_int32 (dict, "count", &count); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get count"); +                goto out; +        } + + +        ret = dict_get_str (dict, "bricks", &bricks); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); +                goto out; +        } + +        ret = glusterd_op_perform_add_bricks (volinfo, count, bricks); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to add bricks"); +                goto out; +        } + +        volinfo->defrag_status = 0; + +        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); +        if (ret) +                goto out; + +        if (GLUSTERD_STATUS_STARTED == volinfo->status) +                ret = glusterd_check_generate_start_nfs (); + +out: +        return ret; +} + +int +glusterd_op_remove_brick (dict_t *dict) +{ +        int                                     ret = -1; +        char                                    *volname = NULL; +        glusterd_volinfo_t                      *volinfo = NULL; +        char                                    *brick = NULL; +        int32_t                                 count = 0; +        int32_t                                 i = 1; +        char                                    key[256] = {0,}; + +        ret = dict_get_str (dict, "volname", &volname); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        ret = glusterd_volinfo_find (volname, &volinfo); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); +                goto out; +        } + +        ret = dict_get_int32 (dict, "count", &count); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get count"); +                goto out; +        } + + +        while ( i <= count) { +                snprintf (key, 256, "brick%d", i); +                ret = dict_get_str (dict, key, &brick); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, "Unable to get %s", key); +                        goto out; +                } + +                ret = glusterd_op_perform_remove_brick (volinfo, brick); +                if (ret) +                        goto out; +                i++; +        } + +        ret = glusterd_create_volfiles_and_notify_services (volinfo); +        if (ret) +                goto out; + +        volinfo->defrag_status = 0; + +        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); + +        if (ret) +                goto out; + +        if (GLUSTERD_STATUS_STARTED == volinfo->status) +                ret = glusterd_check_generate_start_nfs (); + +out: +        return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c new file mode 100644 index 000000000..49654220b --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c @@ -0,0 +1,1579 @@ +/* +  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/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "cli1.h" +#include "glusterd.h" +#include "glusterd-op-sm.h" +#include "glusterd-store.h" +#include "glusterd-utils.h" +#include "glusterd-volgen.h" +#include "run.h" + +#include <signal.h> + +static char *gsync_reserved_opts[] = { +        "gluster-command", +        "pid-file", +        "state-file", +        "session-owner", +        NULL +}; + +int +glusterd_handle_gsync_set (rpcsvc_request_t *req) +{ +        int32_t                 ret     = 0; +        dict_t                  *dict   = NULL; +        gf1_cli_gsync_set_req   cli_req = {{0},}; +        glusterd_op_t           cli_op = GD_OP_GSYNC_SET; +        char                    *master = NULL; +        char                    *slave = NULL; +        char                    operation[256] = {0,}; +        int                     type = 0; +        glusterd_conf_t         *priv   = NULL; +        char                    *host_uuid = NULL; + +        GF_ASSERT (req); +        GF_ASSERT (THIS); +        GF_ASSERT (THIS->private); + +        priv = THIS->private; + +        if (!gf_xdr_to_cli_gsync_set_req (req->msg[0], &cli_req)) { +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        if (cli_req.dict.dict_len) { +                dict = dict_new (); +                if (!dict) +                        goto out; + +                ret = dict_unserialize (cli_req.dict.dict_val, +                                        cli_req.dict.dict_len, +                                        &dict); +                if (ret < 0) { +                        gf_log ("glusterd", GF_LOG_ERROR, "failed to " +                                "unserialize req-buffer to dictionary"); +                        goto out; +                } else { +                        dict->extra_stdfree = cli_req.dict.dict_val; +                } + +                host_uuid = gf_strdup (uuid_utoa(priv->uuid)); +                if (host_uuid == NULL) { +                        gf_log ("glusterd", GF_LOG_ERROR, "failed to get" +                                "the uuid of the host machine"); +                        ret = -1; +                        goto out; +                } +                ret = dict_set_dynstr (dict, "host-uuid", host_uuid); +                if (ret) +                        goto out; + +        } + +        ret = dict_get_str (dict, "master", &master); +        if (ret < 0) { +                gf_log ("", GF_LOG_INFO, "master not found, while handling" +                         GEOREP" options"); +                master = "(No Master)"; +        } + +        ret = dict_get_str (dict, "slave", &slave); +        if (ret < 0) { +                gf_log ("", GF_LOG_INFO, "slave not not found, while" +                        "handling "GEOREP" options"); +                slave = "(No Slave)"; +        } + +        ret = dict_get_int32 (dict, "type", &type); +        if (ret < 0) { +                gf_log ("", GF_LOG_WARNING, "command type not found, while" +                        "handling "GEOREP" options"); +                goto out; +        } + +        switch (type) { + +        case GF_GSYNC_OPTION_TYPE_START: +                strncpy (operation, "start", sizeof (operation)); +                break; + +        case GF_GSYNC_OPTION_TYPE_STOP: +                strncpy (operation, "stop", sizeof (operation)); +                break; + +        case GF_GSYNC_OPTION_TYPE_CONFIG: +                strncpy (operation, "config", sizeof (operation)); +                break; + +        case GF_GSYNC_OPTION_TYPE_STATUS: +                strncpy (operation, "status", sizeof (operation)); +                break; +        } + +        gf_cmd_log ("volume "GEOREP, " %s command on %s,%s", operation, master, +                    slave); +        ret = glusterd_op_begin (req, GD_OP_GSYNC_SET, dict); +        gf_cmd_log ("volume "GEOREP, " %s command on %s,%s %s  ", operation, +                    master, slave, (ret != 0)? "FAILED" : "SUCCEEDED"); + +out: +        glusterd_friend_sm (); +        glusterd_op_sm (); + +        if (ret) { +                if (dict) +                        dict_unref (dict); +                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, +                                                     NULL, "operation failed"); +        } +        return ret; +} + + +/***** + * + * glusterd_urltransform* internal API + * + *****/ + +static void +glusterd_urltransform_init (runner_t *runner, const char *transname) +{ +        runinit (runner); +        runner_add_arg (runner, GSYNCD_PREFIX"/gsyncd"); +        runner_argprintf (runner, "--%s-url", transname); +} + +static void +glusterd_urltransform_add (runner_t *runner, const char *url) +{ +        runner_add_arg (runner, url); +} + +static void +_glusterd_urltransform_add_iter (dict_t *dict, char *key, data_t *value, void *data) +{ +        runner_t *runner = (runner_t *)data; +        char *slave = NULL; + +        slave = strchr (value->data, ':'); +        GF_ASSERT (slave); +        slave++; +        runner_add_arg (runner, slave); +} + +static void +glusterd_urltransform_free (char **linearr, unsigned n) +{ +        int i = 0; + +        for (; i < n; i++) +                GF_FREE (linearr[i]); + +        GF_FREE (linearr); +} + +static int +glusterd_urltransform (runner_t *runner, char ***linearrp) +{ +        char **linearr = NULL; +        char *line = NULL; +        unsigned arr_len = 32; +        unsigned arr_idx = 0; +        gf_boolean_t error = _gf_false; + +        linearr = GF_CALLOC (arr_len, sizeof (char *), gf_gld_mt_linearr); +        if (!linearr) { +                error = _gf_true; +                goto out; +        } + +        runner_redir (runner, STDOUT_FILENO, RUN_PIPE); +        if (runner_start (runner) != 0) { +                gf_log ("", GF_LOG_ERROR, "spawning child failed"); + +                error = _gf_true; +                goto out; +        } + +        arr_idx = 0; +        for (;;) { +                line = GF_MALLOC (1024, gf_gld_mt_linebuf); +                if (!line) { +                        error = _gf_true; +                        goto out; +                } + +                if (fgets (line, 1024, runner_chio (runner, STDOUT_FILENO)) == +                    NULL) +                        break; + +                if (line[strlen (line) - 1] != '\n') { +                        GF_FREE (line); +                        error = _gf_true; +                        goto out; +                } +                line[strlen (line) - 1] = '\0'; + +                if (arr_idx == arr_len) { +                        arr_len <<= 1; +                        linearr = GF_REALLOC (linearr, arr_len); +                        if (!linearr) { +                                GF_FREE (line); +                                error = _gf_true; +                                goto out; +                        } +                } +                linearr[arr_idx] = line; + +                arr_idx++; +        } + + out: + +        /* XXX chpid field is not exported by run API +         * but runner_end() does not abort the invoked +         * process (ie. it might block in waitpid(2)) +         * so we resort to a manual kill a the private field +         */ +        if (error && runner->chpid > 0) +                kill (runner->chpid, SIGKILL); + +        if (runner_end (runner) != 0) +                error = _gf_true; + +        if (error) { +                gf_log ("", GF_LOG_ERROR, "reading data from child failed"); +                glusterd_urltransform_free (linearr, arr_idx); +                return -1; +        } + +        *linearrp = linearr; +        return arr_idx; +} + +static int +glusterd_urltransform_single (const char *url, const char *transname, +                              char ***linearrp) +{ +        runner_t runner = {0,}; + +        glusterd_urltransform_init (&runner, transname); +        glusterd_urltransform_add (&runner, url); +        return glusterd_urltransform (&runner, linearrp); +} + + +struct dictidxmark { +        unsigned isrch; +        unsigned ithis; +        char *ikey; +}; + +static void +_dict_mark_atindex (dict_t *dict, char *key, data_t *value, void *data) +{ +        struct dictidxmark *dim = data; + +        if (dim->isrch == dim->ithis) +                dim->ikey = key; + +        dim->ithis++; +} + +static char * +dict_get_by_index (dict_t *dict, unsigned i) +{ +        struct dictidxmark dim = {0,}; + +        dim.isrch = i; +        dict_foreach (dict, _dict_mark_atindex, &dim); + +        return dim.ikey; +} + +static int +glusterd_get_slave (glusterd_volinfo_t *vol, const char *slaveurl, char **slavekey) +{ +        runner_t runner = {0,}; +        int n = 0; +        int i = 0; +        char **linearr = NULL; + +        glusterd_urltransform_init (&runner, "canonicalize"); +        dict_foreach (vol->gsync_slaves, _glusterd_urltransform_add_iter, &runner); +        glusterd_urltransform_add (&runner, slaveurl); + +        n = glusterd_urltransform (&runner, &linearr); +        if (n == -1) +                return -2; + +        for (i = 0; i < n - 1; i++) { +                if (strcmp (linearr[i], linearr[n - 1]) == 0) +                        break; +        } +        glusterd_urltransform_free (linearr, i); + +        if (i < n - 1) +                *slavekey = dict_get_by_index (vol->gsync_slaves, i); +        else +                i = -1; + +        return i; +} + + +static int +glusterd_query_extutil (char *resbuf, runner_t *runner) +{ +        char               *ptr = NULL; +        int                 ret = 0; + +        runner_redir (runner, STDOUT_FILENO, RUN_PIPE); +        if (runner_start (runner) != 0) { +                gf_log ("", GF_LOG_ERROR, "spawning child failed"); + +                return -1; +        } + +        ptr = fgets(resbuf, PATH_MAX, runner_chio (runner, STDOUT_FILENO)); +        if (ptr) +                resbuf[strlen(resbuf)-1] = '\0'; //strip off \n + +        ret = runner_end (runner); +        if (ret) +                gf_log ("", GF_LOG_ERROR, "reading data from child failed"); + +        return ret ? -1 : 0; +} + +int +glusterd_gsync_get_param_file (char *prmfile, const char *param, char *master, +                               char *slave, char *gl_workdir) +{ +        runner_t            runner = {0,}; + +        runinit (&runner); +        runner_add_args  (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); +        runner_argprintf (&runner, "%s/"GSYNC_CONF, gl_workdir); +        runner_argprintf (&runner, ":%s", master); +        runner_add_args  (&runner, slave, "--config-get", NULL); +        runner_argprintf (&runner, "%s-file", param); + +        return glusterd_query_extutil (prmfile, &runner); +} + +static int +gsyncd_getpidfile (char *master, char *slave, char *pidfile) +{ +        int                ret             = -1; +        glusterd_conf_t    *priv  = NULL; + +        GF_ASSERT (THIS); +        GF_ASSERT (THIS->private); + +        priv = THIS->private; + +        GF_VALIDATE_OR_GOTO ("gsync", master, out); +        GF_VALIDATE_OR_GOTO ("gsync", slave, out); + +        ret = glusterd_gsync_get_param_file (pidfile, "pid", master, +                                              slave, priv->workdir); +        if (ret == -1) { +                ret = -2; +                gf_log ("", GF_LOG_WARNING, "failed to create the pidfile string"); +                goto out; +        } + +        ret = open (pidfile, O_RDWR); + + out: +        return ret; +} + +static int +gsync_status_byfd (int fd) +{ +        GF_ASSERT (fd >= -1); + +        if (lockf (fd, F_TEST, 0) == -1 && +            (errno == EAGAIN || errno == EACCES)) +                /* gsyncd keeps the pidfile locked */ +                return 0; + +        return -1; +} + +/* status: return 0 when gsync is running + * return -1 when not running + */ +int +gsync_status (char *master, char *slave, int *status) +{ +        char pidfile[PATH_MAX] = {0,}; +        int  fd                = -1; + +        fd = gsyncd_getpidfile (master, slave, pidfile); +        if (fd == -2) +                return -1; + +        *status = gsync_status_byfd (fd); + +        close (fd); +        return 0; +} + + +int32_t +glusterd_gsync_volinfo_dict_set (glusterd_volinfo_t *volinfo, +                                 char *key, char *value) +{ +        int32_t  ret            = -1; +        char    *gsync_status   = NULL; + +        gsync_status = gf_strdup (value); +        if (!gsync_status) { +                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); +                goto out; +        } + +        ret = dict_set_dynstr (volinfo->dict, key, gsync_status); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to set dict"); +                goto out; +        } + +        ret = 0; +out: +        return 0; +} + +int +gsync_verify_config_options (dict_t *dict, char **op_errstr) +{ +        char  **resopt    = NULL; +        int     i         = 0; +        char   *subop     = NULL; +        char   *slave     = NULL; +        char   *op_name   = NULL; +        char   *op_value  = NULL; +        gf_boolean_t banned = _gf_true; + +        if (dict_get_str (dict, "subop", &subop) != 0) { +                gf_log ("", GF_LOG_WARNING, "missing subop"); +                *op_errstr = gf_strdup ("Invalid config request"); +                return -1; +        } + +        if (dict_get_str (dict, "slave", &slave) != 0) { +                gf_log ("", GF_LOG_WARNING, GEOREP" CONFIG: no slave given"); +                *op_errstr = gf_strdup ("Slave required"); +                return -1; +        } + +        if (strcmp (subop, "get-all") == 0) +                return 0; + +        if (dict_get_str (dict, "op_name", &op_name) != 0) { +                gf_log ("", GF_LOG_WARNING, "option name missing"); +                *op_errstr = gf_strdup ("Option name missing"); +                return -1; +        } + +        if (runcmd (GSYNCD_PREFIX"/gsyncd", "--config-check", op_name, NULL)) { +                gf_log ("", GF_LOG_WARNING, "Invalid option %s", op_name); +                *op_errstr = gf_strdup ("Invalid option"); + +                return -1; +        } + +        if (strcmp (subop, "get") == 0) +                return 0; + +        if (strcmp (subop, "set") != 0 && strcmp (subop, "del") != 0) { +                gf_log ("", GF_LOG_WARNING, "unknown subop %s", subop); +                *op_errstr = gf_strdup ("Invalid config request"); +                return -1; +        } + +        if (strcmp (subop, "set") == 0 && +            dict_get_str (dict, "op_value", &op_value) != 0) { +                gf_log ("", GF_LOG_WARNING, "missing value for set"); +                *op_errstr = gf_strdup ("missing value"); +        } + +        /* match option name against reserved options, modulo -/_ +         * difference +         */ +        for (resopt = gsync_reserved_opts; *resopt; resopt++) { +                banned = _gf_true; +                for (i = 0; (*resopt)[i] && op_name[i]; i++) { +                        if ((*resopt)[i] == op_name[i] || +                            ((*resopt)[i] == '-' && op_name[i] == '_')) +                                continue; +                        banned = _gf_false; +                } +                if (banned) { +                        gf_log ("", GF_LOG_WARNING, "Reserved option %s", op_name); +                        *op_errstr = gf_strdup ("Reserved option"); + +                        return -1; +                        break; +                } +        } + +        return 0; +} + +static void +_get_status_mst_slv (dict_t *this, char *key, data_t *value, void *data) +{ +        glusterd_gsync_status_temp_t  *param = NULL; +        char                          *slave = NULL; +        int                           ret = 0; + +        param = (glusterd_gsync_status_temp_t *)data; + +        GF_ASSERT (param); +        GF_ASSERT (param->volinfo); + +        slave = strchr(value->data, ':'); +        if (slave) +                slave ++; +        else +                return; + +        ret = glusterd_get_gsync_status_mst_slv(param->volinfo, +                                                slave, param->rsp_dict); + +} + + +static void +_get_max_gsync_slave_num (dict_t *this, char *key, data_t *value, void *data) +{ +        int  tmp_slvnum = 0; +        int *slvnum = (int *)data; + +        sscanf (key, "slave%d", &tmp_slvnum); +        if (tmp_slvnum > *slvnum) +                *slvnum = tmp_slvnum; +} + +static int +glusterd_remove_slave_in_info (glusterd_volinfo_t *volinfo, char *slave, +                               char **op_errstr) +{ +        int   ret = 0; +        char *slavekey = NULL; + +        GF_ASSERT (volinfo); +        GF_ASSERT (slave); + +        ret = glusterd_get_slave (volinfo, slave, &slavekey); +        if (ret < 0) { +                ret++; +                goto out; +        } + +        dict_del (volinfo->gsync_slaves, slavekey); + +        ret = glusterd_store_volinfo (volinfo, +                                      GLUSTERD_VOLINFO_VER_AC_INCREMENT); +        if (ret) { +                 *op_errstr = gf_strdup ("Failed to store the Volume" +                                         "information"); +                goto out; +        } + out: +        gf_log ("", GF_LOG_DEBUG, "returning %d", ret); +        return ret; + +} + +static int +glusterd_gsync_get_uuid (char *slave, glusterd_volinfo_t *vol, +                         uuid_t uuid) +{ +        int   ret = 0; +        char *slavekey = NULL; +        char *slaveentry = NULL; +        char *t = NULL; + +        GF_ASSERT (vol); +        GF_ASSERT (slave); + +        ret = glusterd_get_slave (vol, slave, &slavekey); +        if (ret < 0) { +                /* XXX colliding cases of failure and non-extant +                 * slave... now just doing this as callers of this +                 * function can make sense only of -1 and 0 as retvals; +                 * getting at the proper semanticals will involve +                 * fixing callers as well. +                 */ +                ret = -1; +                goto out; +        } + +        ret = dict_get_str (vol->gsync_slaves, slavekey, &slaveentry); +        GF_ASSERT (ret == 0); + +        t = strchr (slaveentry, ':'); +        GF_ASSERT (t); +        *t = '\0'; +        ret = uuid_parse (slaveentry, uuid); +        *t = ':'; + + out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +static int +glusterd_check_gsync_running_local (char *master, char *slave, +                                    gf_boolean_t *is_run) +{ +        int                 ret    = -1; +        int                 ret_status = 0; + +        GF_ASSERT (master); +        GF_ASSERT (slave); +        GF_ASSERT (is_run); + +        *is_run = _gf_false; +        ret = gsync_status (master, slave, &ret_status); +        if (ret == 0 && ret_status == 0) { +                *is_run = _gf_true; +        } else if (ret == -1) { +                gf_log ("", GF_LOG_WARNING, GEOREP" validation " +                        " failed"); +                goto out; +        } +        ret = 0; + out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; + +} + +static int +glusterd_store_slave_in_info (glusterd_volinfo_t *volinfo, char *slave, +                              char *host_uuid, char **op_errstr) +{ +        int    ret = 0; +        int    maxslv = 0; +        char **linearr = NULL; +        char  *value = NULL; +        char  *slavekey = NULL; +        char  *slaveentry = NULL; +        char   key[512] = {0, }; +        char  *t = NULL; + +        GF_ASSERT (volinfo); +        GF_ASSERT (slave); +        GF_ASSERT (host_uuid); + +        ret = glusterd_get_slave (volinfo, slave, &slavekey); +        switch (ret) { +        case -2: +                ret = -1; +                goto out; +        case -1: +                                break; +        default: +                GF_ASSERT (ret > 0); +                ret = dict_get_str (volinfo->gsync_slaves, slavekey, &slaveentry); +                GF_ASSERT (ret == 0); + +                /* same-name + same-uuid slave entries should have been filtered +                 * out in glusterd_op_verify_gsync_start_options(), so we can +                 * assert an uuid mismatch +                 */ +                t = strtail (slaveentry, host_uuid); +                GF_ASSERT (!t || *t != ':') + +                gf_log ("", GF_LOG_ERROR, GEOREP" has already been invoked for " +                                          "the %s (master) and %s (slave) " +                                          "from a different machine", +                                           volinfo->volname, slave); +                *op_errstr = gf_strdup (GEOREP" already running in an an" +                                        "another machine"); +                ret = -1; +                goto out; +        } + +        ret = glusterd_urltransform_single (slave, "normalize", &linearr); +        if (ret == -1) +                goto out; + +        ret = gf_asprintf (&value,  "%s:%s", host_uuid, linearr[0]); +        glusterd_urltransform_free (linearr, 1); +        if (ret  == -1) +                goto out; + +        dict_foreach (volinfo->gsync_slaves, _get_max_gsync_slave_num, &maxslv); +        snprintf (key, 512, "slave%d", maxslv + 1); +        ret = dict_set_dynstr (volinfo->gsync_slaves, key, value); +        if (ret) +                goto out; + +        ret = glusterd_store_volinfo (volinfo, +                                      GLUSTERD_VOLINFO_VER_AC_INCREMENT); +        if (ret) { +                *op_errstr = gf_strdup ("Failed to store the Volume " +                                        "information"); +                goto out; +        } +        ret = 0; + out: +        return ret; +} + + +static int +glusterd_op_verify_gsync_start_options (glusterd_volinfo_t *volinfo, +                                        char *slave, char **op_errstr) +{ +        int                     ret = -1; +        gf_boolean_t            is_running = _gf_false; +        char                    msg[2048] = {0}; +        uuid_t                  uuid = {0}; +        glusterd_conf_t         *priv = NULL; +        xlator_t                *this = NULL; + +        this = THIS; + +        GF_ASSERT (volinfo); +        GF_ASSERT (slave); +        GF_ASSERT (op_errstr); +        GF_ASSERT (this && this->private); + +        priv  = this->private; + +        if (GLUSTERD_STATUS_STARTED != volinfo->status) { +                snprintf (msg, sizeof (msg), "Volume %s needs to be started " +                          "before "GEOREP" start", volinfo->volname); +                goto out; +        } +        /*Check if the gsync is already started in cmd. inited host +         * If so initiate add it into the glusterd's priv*/ +        ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); +        if ((ret == 0) && (uuid_compare (priv->uuid, uuid) == 0)) { +                ret = glusterd_check_gsync_running_local (volinfo->volname, +                                                          slave, &is_running); +                if (ret) { +                        snprintf (msg, sizeof (msg), GEOREP" start option " +                                  "validation failed "); +                        goto out; +                } +                if (_gf_true == is_running) { +                        snprintf (msg, sizeof (msg), GEOREP " session between" +                                  " %s & %s already started", volinfo->volname, +                                  slave); +                        ret = -1; +                        goto out; +                } +        } +        ret = 0; +out: +        if (ret && (msg[0] != '\0')) { +                *op_errstr = gf_strdup (msg); +        } +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +glusterd_check_gsync_running (glusterd_volinfo_t *volinfo, gf_boolean_t *flag) +{ + +        GF_ASSERT (volinfo); +        GF_ASSERT (flag); + +        if (volinfo->gsync_slaves->count) +                *flag = _gf_true; +        else +                *flag = _gf_false; + +        return 0; +} + +static int +glusterd_op_verify_gsync_running (glusterd_volinfo_t *volinfo, +                                  char *slave, char **op_errstr) +{ +        int                     ret = -1; +        char                    msg[2048] = {0}; +        uuid_t                  uuid = {0}; +        glusterd_conf_t         *priv = NULL; + +        GF_ASSERT (THIS && THIS->private); +        GF_ASSERT (volinfo); +        GF_ASSERT (slave); +        GF_ASSERT (op_errstr); + +        priv = THIS->private; + +        if (GLUSTERD_STATUS_STARTED != volinfo->status) { +                snprintf (msg, sizeof (msg), "Volume %s needs to be started " +                          "before "GEOREP" start", volinfo->volname); + +                goto out; +        } +        ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); +        if (ret == -1) { +                snprintf (msg, sizeof (msg), GEOREP" session between %s & %s" +                          " not active", volinfo->volname, slave); +                goto out; +        } + +        ret = 0; +out: +        if (ret && (msg[0] != '\0')) { +                *op_errstr = gf_strdup (msg); +        } +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +static int +glusterd_verify_gsync_status_opts (dict_t *dict, char **op_errstr) +{ +        char               *slave  = NULL; +        char               *volname = NULL; +        char               errmsg[PATH_MAX] = {0, }; +        gf_boolean_t       exists = _gf_false; +        glusterd_volinfo_t *volinfo = NULL; +        int                ret = 0; + +        ret = dict_get_str (dict, "master", &volname); +        if (ret < 0) { +                ret = 0; +                goto out; +        } + +        exists = glusterd_check_volume_exists (volname); +        ret = glusterd_volinfo_find (volname, &volinfo); +        if ((ret) || (!exists)) { +                gf_log ("", GF_LOG_WARNING, "volume name does not exist"); +                snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" +                          " exist", volname); +                *op_errstr = gf_strdup (errmsg); +                ret = -1; +                goto out; +        } + +        ret = dict_get_str (dict, "slave", &slave); +        if (ret < 0) { +                ret = 0; +                goto out; +        } + + out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; + +} + + +static int +glusterd_op_gsync_args_get (dict_t *dict, char **op_errstr, +                            char **master, char **slave) +{ + +        int             ret = -1; +        GF_ASSERT (dict); +        GF_ASSERT (op_errstr); +        GF_ASSERT (master); +        GF_ASSERT (slave); + +        ret = dict_get_str (dict, "master", master); +        if (ret < 0) { +                gf_log ("", GF_LOG_WARNING, "master not found"); +                *op_errstr = gf_strdup ("master not found"); +                goto out; +        } + +        ret = dict_get_str (dict, "slave", slave); +        if (ret < 0) { +                gf_log ("", GF_LOG_WARNING, "slave not found"); +                *op_errstr = gf_strdup ("slave not found"); +                goto out; +        } + + +        ret = 0; +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr) +{ +        int                     ret     = 0; +        int                     type    = 0; +        char                    *volname = NULL; +        char                    *slave   = NULL; +        gf_boolean_t            exists   = _gf_false; +        glusterd_volinfo_t      *volinfo = NULL; +        char                    errmsg[PATH_MAX] = {0,}; + + +        ret = dict_get_int32 (dict, "type", &type); +        if (ret < 0) { +                gf_log ("", GF_LOG_WARNING, "command type not found"); +                *op_errstr = gf_strdup ("command unsuccessful"); +                goto out; +        } + +        switch (type) { +        case GF_GSYNC_OPTION_TYPE_STATUS: +                ret = glusterd_verify_gsync_status_opts (dict, op_errstr); + +                goto out; +        case GF_GSYNC_OPTION_TYPE_CONFIG: +                ret = gsync_verify_config_options (dict, op_errstr); + +                goto out; +        } + +        ret = glusterd_op_gsync_args_get (dict, op_errstr, &volname, &slave); +        if (ret) +                goto out; + +        exists = glusterd_check_volume_exists (volname); +        ret = glusterd_volinfo_find (volname, &volinfo); +        if ((ret) || (!exists)) { +                gf_log ("", GF_LOG_WARNING, "volume name does not exist"); +                snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" +                          " exist", volname); +                *op_errstr = gf_strdup (errmsg); +                ret = -1; +                goto out; +        } + +        switch (type) { +        case GF_GSYNC_OPTION_TYPE_START: +                ret = glusterd_op_verify_gsync_start_options (volinfo, slave, +                                                              op_errstr); +                break; +        case GF_GSYNC_OPTION_TYPE_STOP: +                ret = glusterd_op_verify_gsync_running (volinfo, slave, +                                                        op_errstr); +                break; +        } + +out: +        return ret; +} + +int +stop_gsync (char *master, char *slave, char **msg) +{ +        int32_t         ret     = 0; +        int             pfd     = -1; +        pid_t           pid     = 0; +        char            pidfile[PATH_MAX] = {0,}; +        char            buf [1024] = {0,}; +        int             i       = 0; +        glusterd_conf_t *priv = NULL; + +        GF_ASSERT (THIS); +        GF_ASSERT (THIS->private); + +        priv = THIS->private; + +        pfd = gsyncd_getpidfile (master, slave, pidfile); +        if (pfd == -2) { +                gf_log ("", GF_LOG_ERROR, GEOREP" stop validation " +                        " failed for %s & %s", master, slave); +                ret = -1; +                goto out; +        } +        if (gsync_status_byfd (pfd) == -1) { +                gf_log ("", GF_LOG_ERROR, "gsyncd b/w %s & %s is not" +                        " running", master, slave); +                if (msg) +                        *msg = gf_strdup ("Warning: "GEOREP" session was in " +                                          "corrupt  state"); +                /* monitor gsyncd already dead */ +                goto out; +        } + +        ret = read (pfd, buf, 1024); +        if (ret > 0) { +                pid = strtol (buf, NULL, 10); +                ret = kill (-pid, SIGTERM); +                if (ret) { +                        gf_log ("", GF_LOG_WARNING, +                                "failed to kill gsyncd"); +                        goto out; +                } +                for (i = 0; i < 20; i++) { +                        if (gsync_status_byfd (pfd) == -1) { +                                /* monitor gsyncd is dead but worker may +                                 * still be alive, give some more time +                                 * before SIGKILL (hack) +                                 */ +                                usleep (50000); +                                break; +                        } +                        usleep (50000); +                } +                kill (-pid, SIGKILL); +                unlink (pidfile); +        } +        ret = 0; + +out: +        close (pfd); +        return ret; +} + +int +glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave, +                                      dict_t *resp_dict); + +int +glusterd_gsync_configure (glusterd_volinfo_t *volinfo, char *slave, +                          dict_t *dict, dict_t *resp_dict, char **op_errstr) +{ +        int32_t         ret     = -1; +        char            *op_name = NULL; +        char            *op_value = NULL; +        runner_t        runner    = {0,}; +        glusterd_conf_t *priv   = NULL; +        char            *subop  = NULL; +        char            *master = NULL; + +        GF_ASSERT (slave); +        GF_ASSERT (op_errstr); +        GF_ASSERT (dict); +        GF_ASSERT (resp_dict); + +        ret = dict_get_str (dict, "subop", &subop); +        if (ret != 0) +                goto out; + +        if (strcmp (subop, "get") == 0 || strcmp (subop, "get-all") == 0) { +                /* deferred to cli */ +                gf_log ("", GF_LOG_DEBUG, "Returning 0"); +                return 0; +        } + +        ret = dict_get_str (dict, "op_name", &op_name); +        if (ret != 0) +                goto out; + +        if (strcmp (subop, "set") == 0) { +                ret = dict_get_str (dict, "op_value", &op_value); +                if (ret != 0) +                        goto out; +        } + +        if (THIS) +                priv = THIS->private; +        if (priv == NULL) { +                gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); +                *op_errstr = gf_strdup ("glusterd defunct"); +                goto out; +        } + +        master = ""; +        runinit (&runner); +        runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); +        runner_argprintf (&runner, "%s/"GSYNC_CONF, priv->workdir); +        if (volinfo) { +                master = volinfo->volname; +                runner_argprintf (&runner, ":%s", master); +        } +        runner_add_arg (&runner, slave); +        runner_argprintf (&runner, "--config-%s", subop); +        runner_add_arg (&runner, op_name); +        if (op_value) +                runner_add_arg (&runner, op_value); +        ret = runner_run (&runner); +        if (ret) { +                gf_log ("", GF_LOG_WARNING, "gsyncd failed to " +                        "%s %s option for %s %s peers", +                        subop, op_name, master, slave); + +                gf_asprintf (op_errstr, GEOREP" config-%s failed for %s %s", +                             subop, master, slave); + +                goto out; +        } +        ret = 0; +        gf_asprintf (op_errstr, "config-%s successful", subop); + +out: +        if (!ret && volinfo) { +                ret = glusterd_check_restart_gsync_session (volinfo, slave, +                                                            resp_dict); +                if (ret) +                        *op_errstr = gf_strdup ("internal error"); +        } + +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +glusterd_gsync_read_frm_status (char *path, char *data) +{ +        int                 ret = 0; +        FILE               *status_file = NULL; + +        GF_ASSERT (path); +        GF_ASSERT (data); +        status_file = fopen (path, "r"); +        if (status_file  == NULL) { +                gf_log ("", GF_LOG_WARNING, "Unable to read gsyncd status" +                        " file"); +                return -1; +        } +        ret = fread (data, PATH_MAX, 1, status_file); +        if (ret < 0) { +                gf_log ("", GF_LOG_WARNING, "Status file of gsyncd is corrupt"); +                return -1; +        } + +        data[strlen(data)-1] = '\0'; + +        return 0; +} + +int +glusterd_read_status_file (char *master, char *slave, +                           dict_t *dict) +{ +        glusterd_conf_t  *priv = NULL; +        int              ret = 0; +        char             statusfile[PATH_MAX] = {0, }; +        char             buff[PATH_MAX] = {0, }; +        char             mst[PATH_MAX] = {0, }; +        char             slv[PATH_MAX] = {0, }; +        char             sts[PATH_MAX] = {0, }; +        int              gsync_count = 0; +        int              status = 0; + +        GF_ASSERT (THIS); +        GF_ASSERT (THIS->private); + +        priv = THIS->private; +        ret = glusterd_gsync_get_param_file (statusfile, "state", master, +                                             slave, priv->workdir); +        if (ret) { +                gf_log ("", GF_LOG_WARNING, "Unable to get the name of status" +                        "file for %s(master), %s(slave)", master, slave); +                goto out; + +        } + +        ret = gsync_status (master, slave, &status); +        if (ret == 0 && status == -1) { +                strncpy (buff, "corrupt", sizeof (buff)); +                goto done; +        } else if (ret == -1) +                goto out; + +        ret = glusterd_gsync_read_frm_status (statusfile, buff); +        if (ret) { +                gf_log ("", GF_LOG_WARNING, "Unable to read the status" +                        "file for %s(master), %s(slave)", master, slave); +                goto out; + +        } + + done: +        ret = dict_get_int32 (dict, "gsync-count", &gsync_count); + +        if (ret) +                gsync_count = 1; +        else +                gsync_count++; + +        snprintf (mst, sizeof (mst), "master%d", gsync_count); +        ret = dict_set_dynstr (dict, mst, gf_strdup (master)); +        if (ret) +                goto out; + +        snprintf (slv, sizeof (slv), "slave%d", gsync_count); +        ret = dict_set_dynstr (dict, slv, gf_strdup (slave)); +        if (ret) +                goto out; + +        snprintf (sts, sizeof (slv), "status%d", gsync_count); +        ret = dict_set_dynstr (dict, sts, gf_strdup (buff)); +        if (ret) +                goto out; +        ret = dict_set_int32 (dict, "gsync-count", gsync_count); +        if (ret) +                goto out; + +        ret = 0; + out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d ", ret); +        return ret; +} + +int +glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave, +                                      dict_t *resp_dict) +{ + +        int                    ret = 0; +        uuid_t                 uuid = {0, }; +        glusterd_conf_t        *priv = NULL; +        char                   *status_msg = NULL; + +        GF_ASSERT (volinfo); +        GF_ASSERT (slave); +        GF_ASSERT (THIS); +        GF_ASSERT (THIS->private); + +        priv = THIS->private; + +        if (glusterd_gsync_get_uuid (slave, volinfo, uuid)) +                /* session does not exist, nothing to do */ +                goto out; +        if (uuid_compare (priv->uuid, uuid) == 0) { +                ret = stop_gsync (volinfo->volname, slave, &status_msg); +                if (ret == 0 && status_msg) +                        ret = dict_set_str (resp_dict, "gsync-status", +                                            status_msg); +                if (ret == 0) +                        ret = glusterd_start_gsync (volinfo, slave, +                                                    uuid_utoa(priv->uuid), NULL); +        } + + out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int32_t +glusterd_marker_create_volfile (glusterd_volinfo_t *volinfo) +{ +        int32_t          ret     = 0; + +        ret = glusterd_create_volfiles_and_notify_services (volinfo); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to create volfile" +                        " for setting of marker while '"GEOREP" start'"); +                ret = -1; +                goto out; +        } + +        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); +        if (ret) +                goto out; + +        if (GLUSTERD_STATUS_STARTED == volinfo->status) +                ret = glusterd_check_generate_start_nfs (); +        ret = 0; +out: +        return ret; +} + +int +glusterd_set_marker_gsync (glusterd_volinfo_t *volinfo) +{ +        int                      ret     = -1; +        int                      marker_set = _gf_false; +        char                    *gsync_status = NULL; +        glusterd_conf_t         *priv = NULL; + +        GF_ASSERT (THIS); +        GF_ASSERT (THIS->private); + +        priv = THIS->private; + +        marker_set = glusterd_volinfo_get_boolean (volinfo, VKEY_MARKER_XTIME); +        if (marker_set == -1) { +                gf_log ("", GF_LOG_ERROR, "failed to get the marker status"); +                ret = -1; +                goto out; +        } + +        if (marker_set == _gf_false) { +                gsync_status = gf_strdup ("on"); +                if (gsync_status == NULL) { +                        ret = -1; +                        goto out; +                } + +                ret = glusterd_gsync_volinfo_dict_set (volinfo, +                                                       VKEY_MARKER_XTIME, gsync_status); +                if (ret < 0) +                        goto out; + +                ret = glusterd_marker_create_volfile (volinfo); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, "Setting dict failed"); +                        goto out; +                } +        } +        ret = 0; + +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + + + + +int +glusterd_get_gsync_status_mst_slv( glusterd_volinfo_t *volinfo, +                                   char *slave, dict_t *rsp_dict) +{ +        uuid_t             uuid = {0, }; +        glusterd_conf_t    *priv = NULL; +        int                ret = 0; + +        GF_ASSERT (volinfo); +        GF_ASSERT (slave); +        GF_ASSERT (THIS); +        GF_ASSERT (THIS->private); + +        priv = THIS->private; + +        ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); +        if ((ret == 0) && (uuid_compare (priv->uuid, uuid) != 0)) +                goto out; + +        if (ret) { +                ret = 0; +                gf_log ("", GF_LOG_INFO, "geo-replication status %s %s :" +                        "session is not active", volinfo->volname, slave); +                goto out; +        } + +        ret = glusterd_read_status_file (volinfo->volname, slave, rsp_dict); + out: +        gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); +        return ret; +} + +static int +glusterd_get_gsync_status_mst (glusterd_volinfo_t *volinfo, dict_t *rsp_dict) +{ +        glusterd_gsync_status_temp_t  param = {0, }; + +        GF_ASSERT (volinfo); + +        param.rsp_dict = rsp_dict; +        param.volinfo = volinfo; +        dict_foreach (volinfo->gsync_slaves, _get_status_mst_slv, ¶m); + +        return 0; +} + +static int +glusterd_get_gsync_status_all ( dict_t *rsp_dict) +{ + +        int32_t                 ret = 0; +        glusterd_conf_t         *priv = NULL; +        glusterd_volinfo_t      *volinfo = NULL; + +        GF_ASSERT (THIS); +        priv = THIS->private; + +        GF_ASSERT (priv); + +        list_for_each_entry (volinfo, &priv->volumes, vol_list) { +                ret = glusterd_get_gsync_status_mst (volinfo, rsp_dict); +                if (ret) +                        goto out; +        } + +out: +        gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); +        return ret; + +} + +static int +glusterd_get_gsync_status (dict_t *dict, char **op_errstr, dict_t *rsp_dict) +{ +        char               *slave  = NULL; +        char               *volname = NULL; +        char               errmsg[PATH_MAX] = {0, }; +        gf_boolean_t       exists = _gf_false; +        glusterd_volinfo_t *volinfo = NULL; +        int                ret = 0; + + +        ret = dict_get_str (dict, "master", &volname); +        if (ret < 0){ +                ret = glusterd_get_gsync_status_all (rsp_dict); +                goto out; +        } + +        exists = glusterd_check_volume_exists (volname); +        ret = glusterd_volinfo_find (volname, &volinfo); +        if ((ret) || (!exists)) { +                gf_log ("", GF_LOG_WARNING, "volume name does not exist"); +                snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" +                          " exist", volname); +                *op_errstr = gf_strdup (errmsg); +                ret = -1; +                goto out; +        } + + +        ret = dict_get_str (dict, "slave", &slave); +        if (ret < 0) { +                ret = glusterd_get_gsync_status_mst (volinfo, rsp_dict); +                goto out; +        } + +        ret = glusterd_get_gsync_status_mst_slv (volinfo, slave, rsp_dict); + + out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; + + +} + + +int +glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict) +{ +        int32_t             ret     = -1; +        int32_t             type    = -1; +        dict_t             *ctx    = NULL; +        dict_t             *resp_dict = NULL; +        char               *host_uuid = NULL; +        char               *slave  = NULL; +        char               *volname = NULL; +        glusterd_volinfo_t *volinfo = NULL; +        glusterd_conf_t    *priv = NULL; +        char               *status_msg = NULL; +        uuid_t              uuid = {0, }; + +        GF_ASSERT (THIS); +        GF_ASSERT (THIS->private); +        GF_ASSERT (dict); +        GF_ASSERT (op_errstr); + +        priv = THIS->private; + +        ret = dict_get_int32 (dict, "type", &type); +        if (ret < 0) +                goto out; + +        ret = dict_get_str (dict, "host-uuid", &host_uuid); +        if (ret < 0) +                goto out; + +        ctx = glusterd_op_get_ctx (); +        resp_dict = ctx ? ctx : rsp_dict; +        GF_ASSERT (resp_dict); + +        if (type == GF_GSYNC_OPTION_TYPE_STATUS) { +                ret = glusterd_get_gsync_status (dict, op_errstr, resp_dict); +                goto out; +        } + +        ret = dict_get_str (dict, "slave", &slave); +        if (ret < 0) +                goto out; + +        if (dict_get_str (dict, "master", &volname) == 0) { +                ret = glusterd_volinfo_find (volname, &volinfo); +                if (ret) { +                        gf_log ("", GF_LOG_WARNING, "Volinfo for %s (master) not found", +                                volname); +                        goto out; +                } +        } + +        if (type == GF_GSYNC_OPTION_TYPE_CONFIG) { +                ret = glusterd_gsync_configure (volinfo, slave, dict, resp_dict, +                                                op_errstr); +                goto out; +        } + +        if (!volinfo) { +                ret = -1; +                goto out; +        } + +        if (type == GF_GSYNC_OPTION_TYPE_START) { + +                ret = glusterd_set_marker_gsync (volinfo); +                if (ret != 0) { +                        gf_log ("", GF_LOG_WARNING, "marker start failed"); +                        *op_errstr = gf_strdup ("failed to initialize indexing"); +                        ret = -1; +                        goto out; +                } +                ret = glusterd_store_slave_in_info(volinfo, slave, +                                                   host_uuid, op_errstr); +                if (ret) +                        goto out; + +                ret = glusterd_start_gsync (volinfo, slave, host_uuid, +                                            op_errstr); +        } + +        if (type == GF_GSYNC_OPTION_TYPE_STOP) { + +                ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); +                if (ret) { +                        gf_log ("", GF_LOG_WARNING, GEOREP" is not set up for" +                                "%s(master) and %s(slave)", volname, slave); +                        *op_errstr = strdup (GEOREP" is not set up"); +                        goto out; +                } + +                ret = glusterd_remove_slave_in_info(volinfo, slave, op_errstr); +                if (ret) +                        goto out; + +                if (uuid_compare (priv->uuid, uuid) != 0) { +                        goto out; +                } + +                ret = stop_gsync (volname, slave, &status_msg); +                if (ret == 0 && status_msg) +                        ret = dict_set_str (resp_dict, "gsync-status", +                                            status_msg); +                if (ret != 0) +                        *op_errstr = gf_strdup ("internal error"); +        } + +out: +        gf_log ("", GF_LOG_DEBUG,"Returning %d", ret); +        return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index d13f32500..08ba9bc46 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -855,679 +855,6 @@ glusterd_op_begin (rpcsvc_request_t *req, glusterd_op_t op, void *ctx)          return ret;  } -int -glusterd_handle_create_volume (rpcsvc_request_t *req) -{ -        int32_t                 ret         = -1; -        gf1_cli_create_vol_req  cli_req     = {0,}; -        dict_t                 *dict        = NULL; -        glusterd_brickinfo_t   *brickinfo   = NULL; -        char                   *brick       = NULL; -        char                   *bricks      = NULL; -        char                   *volname     = NULL; -        int                    brick_count = 0; -        char                   *tmpptr      = NULL; -        int                    i           = 0; -        char                   *brick_list  = NULL; -        void                   *cli_rsp     = NULL; -        char                    err_str[2048] = {0,}; -        gf1_cli_create_vol_rsp  rsp         = {0,}; -        glusterd_conf_t        *priv        = NULL; -        xlator_t               *this        = NULL; -        char                   *free_ptr    = NULL; -        char                   *trans_type  = NULL; -        uuid_t                  volume_id   = {0,}; -        glusterd_brickinfo_t    *tmpbrkinfo = NULL; -        glusterd_volinfo_t      tmpvolinfo = {{0},}; - -        GF_ASSERT (req); - -        INIT_LIST_HEAD (&tmpvolinfo.bricks); - -        this = THIS; -        GF_ASSERT(this); - -        priv = this->private; - -        ret = -1; -        if (!gf_xdr_to_cli_create_vol_req (req->msg[0], &cli_req)) { -                //failed to decode msg; -                req->rpc_err = GARBAGE_ARGS; -                snprintf (err_str, sizeof (err_str), "Garbage args received"); -                goto out; -        } - -        gf_log ("glusterd", GF_LOG_INFO, "Received create volume req"); - -        if (cli_req.bricks.bricks_len) { -                /* Unserialize the dictionary */ -                dict  = dict_new (); - -                ret = dict_unserialize (cli_req.bricks.bricks_val, -                                        cli_req.bricks.bricks_len, -                                        &dict); -                if (ret < 0) { -                        gf_log ("glusterd", GF_LOG_ERROR, -                                "failed to " -                                "unserialize req-buffer to dictionary"); -                        snprintf (err_str, sizeof (err_str), "Unable to decode " -                                  "the buffer"); -                        goto out; -                } else { -                        dict->extra_stdfree = cli_req.bricks.bricks_val; -                } -        } - -        ret = dict_get_str (dict, "volname", &volname); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                snprintf (err_str, sizeof (err_str), "Unable to get volume " -                          "name"); -                goto out; -        } -        gf_cmd_log ("Volume create", "on volname: %s attempted", volname); - -        if ((ret = glusterd_check_volume_exists (volname))) { -                snprintf(err_str, 2048, "Volume %s already exists", volname); -                gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); -                goto out; -        } - -        ret = dict_get_int32 (dict, "count", &brick_count); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get count"); -                snprintf (err_str, sizeof (err_str), "Unable to get volume " -                          "brick count"); -                goto out; -        } - -        ret = dict_get_str (dict, "transport", &trans_type); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get transport-type"); -                snprintf (err_str, sizeof (err_str), "Unable to get volume " -                          "transport-type"); -                goto out; -        } -        ret = dict_get_str (dict, "bricks", &bricks); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); -                snprintf (err_str, sizeof (err_str), "Unable to get volume " -                          "bricks"); -                goto out; -        } - -        uuid_generate (volume_id); -        free_ptr = gf_strdup (uuid_utoa (volume_id)); -        ret = dict_set_dynstr (dict, "volume-id", free_ptr); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "unable to set volume-id"); -                snprintf (err_str, sizeof (err_str), "Unable to set volume " -                          "id"); -                goto out; -        } -        free_ptr = NULL; - -        if (bricks) { -                brick_list = gf_strdup (bricks); -                free_ptr = brick_list; -        } - -        gf_cmd_log ("Volume create", "on volname: %s type:%s count:%d bricks:%s", -                    cli_req.volname, ((cli_req.type == 0)? "DEFAULT": -                    ((cli_req.type == 1)? "STRIPE":"REPLICATE")), cli_req.count, -                    bricks); - - -        while ( i < brick_count) { -                i++; -                brick= strtok_r (brick_list, " \n", &tmpptr); -                brick_list = tmpptr; -                ret = glusterd_brickinfo_from_brick (brick, &brickinfo); -                if (ret) { -                        snprintf (err_str, sizeof (err_str), "Unable to get " -                                  "brick info from brick %s", brick); -                        goto out; -                } - -                ret = glusterd_new_brick_validate (brick, brickinfo, err_str, -                                                   sizeof (err_str)); -                if (ret) -                        goto out; -                ret = glusterd_volume_brickinfo_get (brickinfo->uuid, -                                                     brickinfo->hostname, -                                                     brickinfo->path, -                                                     &tmpvolinfo, &tmpbrkinfo); -                if (!ret) { -                        ret = -1; -                        snprintf (err_str, sizeof (err_str), "Brick: %s:%s, %s" -                                  " one of the arguments contain the other", -                                  tmpbrkinfo->hostname, tmpbrkinfo->path, brick); -                        goto out; -                } -                list_add_tail (&brickinfo->brick_list, &tmpvolinfo.bricks); -                brickinfo = NULL; -        } - -        ret = glusterd_op_begin (req, GD_OP_CREATE_VOLUME, dict); -        gf_cmd_log ("Volume create", "on volname: %s %s", volname, -                    (ret != 0) ? "FAILED": "SUCCESS"); - -out: -        if (ret) { -                if (dict) -                        dict_unref (dict); -                rsp.op_ret = -1; -                rsp.op_errno = 0; -                rsp.volname = ""; -                if (err_str[0] == '\0') -                        snprintf (err_str, sizeof (err_str), "Operation failed"); -                rsp.op_errstr = err_str; -                cli_rsp = &rsp; -                glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL, -                                      gf_xdr_serialize_cli_create_vol_rsp, -                                      (xdrproc_t)xdr_gf1_cli_create_vol_rsp); - -                ret = 0; //Client response sent, prevent second response -        } - -        if (free_ptr) -                GF_FREE(free_ptr); - -        glusterd_volume_brickinfos_delete (&tmpvolinfo); -        if (brickinfo) -                glusterd_brickinfo_delete (brickinfo); -        if (cli_req.volname) -                free (cli_req.volname); // its a malloced by xdr - -        glusterd_friend_sm (); -        glusterd_op_sm (); - -        return ret; -} - -int -glusterd_handle_cli_start_volume (rpcsvc_request_t *req) -{ -        int32_t                         ret = -1; -        gf1_cli_start_vol_req           cli_req = {0,}; -        char                            *dup_volname = NULL; -        dict_t                          *dict = NULL; -        glusterd_op_t                   cli_op = GD_OP_START_VOLUME; - -        GF_ASSERT (req); - -        if (!gf_xdr_to_cli_start_vol_req (req->msg[0], &cli_req)) { -                //failed to decode msg; -                req->rpc_err = GARBAGE_ARGS; -                goto out; -        } - -        gf_log ("glusterd", GF_LOG_INFO, "Received start vol req" -                "for volume %s", cli_req.volname); - -        dict = dict_new (); - -        if (!dict) -                goto out; - -        dup_volname = gf_strdup (cli_req.volname); -        if (!dup_volname) -                goto out; - -        ret = dict_set_dynstr (dict, "volname", dup_volname); -        if (ret) -                goto out; - -        ret = dict_set_int32 (dict, "flags", cli_req.flags); -        if (ret) -                goto out; -        ret = glusterd_op_begin (req, GD_OP_START_VOLUME, dict); - -        gf_cmd_log ("volume start","on volname: %s %s", cli_req.volname, -                    ((ret == 0) ? "SUCCESS": "FAILED")); - -out: -        if (ret && dict) -                dict_unref (dict); -        if (cli_req.volname) -                free (cli_req.volname); //its malloced by xdr - -        glusterd_friend_sm (); -        glusterd_op_sm (); - -        if (ret) -                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, -                                                     NULL, "operation failed"); - -        return ret; -} - - -int -glusterd_handle_cli_stop_volume (rpcsvc_request_t *req) -{ -        int32_t                         ret = -1; -        gf1_cli_stop_vol_req           cli_req = {0,}; -        char                            *dup_volname = NULL; -        dict_t                          *dict = NULL; -        glusterd_op_t                   cli_op = GD_OP_STOP_VOLUME; - -        GF_ASSERT (req); - -        if (!gf_xdr_to_cli_stop_vol_req (req->msg[0], &cli_req)) { -                //failed to decode msg; -                req->rpc_err = GARBAGE_ARGS; -                goto out; -        } - -        gf_log ("glusterd", GF_LOG_INFO, "Received stop vol req" -                "for volume %s", cli_req.volname); - -        dict = dict_new (); - -        if (!dict) -                goto out; - -        dup_volname = gf_strdup (cli_req.volname); -        if (!dup_volname) -                goto out; - -        ret = dict_set_dynstr (dict, "volname", dup_volname); -        if (ret) -                goto out; - -        ret = dict_set_int32 (dict, "flags", cli_req.flags); -        if (ret) -                goto out; - -        ret = glusterd_op_begin (req, GD_OP_STOP_VOLUME, dict); -        gf_cmd_log ("Volume stop","on volname: %s %s", cli_req.volname, -                    ((ret)?"FAILED":"SUCCESS")); - -out: -        if (cli_req.volname) -                free (cli_req.volname); //its malloced by xdr - -        glusterd_friend_sm (); -        glusterd_op_sm (); - -        if (ret) { -                if (dict) -                        dict_unref (dict); -                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, -                                                     NULL, "operation failed"); -        } - -        return ret; -} - -int -glusterd_handle_cli_delete_volume (rpcsvc_request_t *req) -{ -        int32_t                           ret = -1; -        gf1_cli_delete_vol_req            cli_req = {0,}; -        glusterd_op_delete_volume_ctx_t   *ctx = NULL; -        glusterd_op_t                     cli_op = GD_OP_DELETE_VOLUME; - -        GF_ASSERT (req); - -        if (!gf_xdr_to_cli_delete_vol_req (req->msg[0], &cli_req)) { -                //failed to decode msg; -                req->rpc_err = GARBAGE_ARGS; -                goto out; -        } -        gf_cmd_log ("Volume delete","on volname: %s attempted", cli_req.volname); - -        gf_log ("glusterd", GF_LOG_INFO, "Received delete vol req" -                "for volume %s", cli_req.volname); - - -        ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_delete_volume_ctx_t); -        if (!ctx) -                goto out; - -        strncpy (ctx->volume_name, cli_req.volname, GD_VOLUME_NAME_MAX); - -        ret = glusterd_op_begin (req, GD_OP_DELETE_VOLUME, ctx); -        gf_cmd_log ("Volume delete", "on volname: %s %s", cli_req.volname, -                   ((ret) ? "FAILED" : "SUCCESS")); - -out: -        if (cli_req.volname) -                free (cli_req.volname); //its malloced by xdr - -        glusterd_friend_sm (); -        glusterd_op_sm (); - -        if (ret) { -                if (ctx) -                        GF_FREE (ctx); - -                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, -                                                     NULL, "operation failed"); -        } - -        return ret; -} - -int -glusterd_handle_add_brick (rpcsvc_request_t *req) -{ -        int32_t                         ret = -1; -        gf1_cli_add_brick_req          cli_req = {0,}; -        dict_t                          *dict = NULL; -        glusterd_brickinfo_t            *brickinfo = NULL; -        char                            *brick = NULL; -        char                            *bricks = NULL; -        char                            *volname = NULL; -        int                             brick_count = 0; -        char                            *tmpptr = NULL; -        int                             i = 0; -        char                            *brick_list = NULL; -        void                            *cli_rsp = NULL; -        char                            err_str[2048] = {0,}; -        gf1_cli_add_brick_rsp           rsp = {0,}; -        glusterd_volinfo_t              *volinfo = NULL; -        glusterd_conf_t                 *priv = NULL; -        xlator_t                        *this = NULL; -        char                            *free_ptr = NULL; -        glusterd_brickinfo_t            *tmpbrkinfo = NULL; -        glusterd_volinfo_t              tmpvolinfo = {{0},}; -        int                             total_bricks = 0; - -        this = THIS; -        GF_ASSERT(this); - -        priv = this->private; - -        GF_ASSERT (req); - -        INIT_LIST_HEAD (&tmpvolinfo.bricks); - -        if (!gf_xdr_to_cli_add_brick_req (req->msg[0], &cli_req)) { -                //failed to decode msg; -                req->rpc_err = GARBAGE_ARGS; -                snprintf (err_str, sizeof (err_str), "Garbage args received"); -                goto out; -        } - -        gf_cmd_log ("Volume add-brick", "on volname: %s attempted", -                    cli_req.volname); -        gf_log ("glusterd", GF_LOG_INFO, "Received add brick req"); - -        if (cli_req.bricks.bricks_len) { -                /* Unserialize the dictionary */ -                dict  = dict_new (); - -                ret = dict_unserialize (cli_req.bricks.bricks_val, -                                        cli_req.bricks.bricks_len, -                                        &dict); -                if (ret < 0) { -                        gf_log ("glusterd", GF_LOG_ERROR, -                                "failed to " -                                "unserialize req-buffer to dictionary"); -                        snprintf (err_str, sizeof (err_str), "Unable to decode " -                                  "the buffer"); -                        goto out; -                } else { -                        dict->extra_stdfree = cli_req.bricks.bricks_val; -                } -        } - -        ret = dict_get_str (dict, "volname", &volname); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                snprintf (err_str, sizeof (err_str), "Unable to get volume " -                          "name"); -                goto out; -        } - -        if (!(ret = glusterd_check_volume_exists (volname))) { -                ret = -1; -                snprintf(err_str, 2048, "Volume %s does not exist", volname); -                gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); -                goto out; -        } - -        ret = dict_get_int32 (dict, "count", &brick_count); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get count"); -                snprintf (err_str, sizeof (err_str), "Unable to get volume " -                          "brick count"); -                goto out; -        } - -        if (!(ret = glusterd_volinfo_find (volname, &volinfo))) { -                if (volinfo->type == GF_CLUSTER_TYPE_NONE) -                        goto brick_val; -                if (!brick_count || !volinfo->sub_count) -                        goto brick_val; - -                total_bricks = volinfo->brick_count + brick_count; -		/* If the brick count is less than sub_count then, allow add-brick only for -		   plain replicate volume since in plain stripe brick_count becoming less than -		   the sub_count is not allowed */ -                if (volinfo->brick_count < volinfo->sub_count && -                    (volinfo->type == GF_CLUSTER_TYPE_REPLICATE)) { -                        if (total_bricks <= volinfo->sub_count) -                                goto brick_val; -                } - -                if ((brick_count % volinfo->sub_count) != 0) { -                        snprintf(err_str, 2048, "Incorrect number of bricks" -                                " supplied %d for type %s with count %d", -                                brick_count, (volinfo->type == 1)? "STRIPE": -                                "REPLICATE", volinfo->sub_count); -                        gf_log("glusterd", GF_LOG_ERROR, "%s", err_str); -                        ret = -1; -                        goto out; -                } -        } else { -                snprintf (err_str, sizeof (err_str), "Unable to get volinfo " -                          "for volume name %s", volname); -                gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); -                goto out; -        } - -brick_val: -        ret = dict_get_str (dict, "bricks", &bricks); -        if (ret) { -                snprintf (err_str, sizeof (err_str), "Unable to get volume " -                          "bricks"); -                gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); -                goto out; -        } - -        if (bricks) -                brick_list = gf_strdup (bricks); -        if (!brick_list) { -                ret = -1; -                snprintf (err_str, sizeof (err_str), "Out of memory"); -                goto out; -        } else { -                free_ptr = brick_list; -        } - -        gf_cmd_log ("Volume add-brick", "volname: %s type %s count:%d bricks:%s" -                    ,volname, ((volinfo->type == 0)? "DEFAULT" : ((volinfo->type -                    == 1)? "STRIPE": "REPLICATE")), brick_count, brick_list); - - -        while ( i < brick_count) { -                i++; -                brick= strtok_r (brick_list, " \n", &tmpptr); -                brick_list = tmpptr; -                brickinfo = NULL; -                ret = glusterd_brickinfo_from_brick (brick, &brickinfo); -                if (ret) { -                        snprintf (err_str, sizeof (err_str), "Unable to get " -                                  "brick info from brick %s", brick); -                        goto out; -                } -                ret = glusterd_new_brick_validate (brick, brickinfo, err_str, -                                                   sizeof (err_str)); -                if (ret) -                        goto out; -                ret = glusterd_volume_brickinfo_get (brickinfo->uuid, -                                                     brickinfo->hostname, -                                                     brickinfo->path, -                                                     &tmpvolinfo, &tmpbrkinfo); -                if (!ret) { -                        ret = -1; -                        snprintf (err_str, sizeof (err_str), "Brick: %s:%s, %s" -                                  " one of the arguments contain the other", -                                  tmpbrkinfo->hostname, tmpbrkinfo->path, brick); -                        goto out; -                } -                list_add_tail (&brickinfo->brick_list, &tmpvolinfo.bricks); -                brickinfo = NULL; -        } - -        ret = glusterd_op_begin (req, GD_OP_ADD_BRICK, dict); -        gf_cmd_log ("Volume add-brick","on volname: %s %s", volname, -                   (ret != 0)? "FAILED" : "SUCCESS"); - -out: -        if (ret) { -                if (dict) -                        dict_unref (dict); -                rsp.op_ret = -1; -                rsp.op_errno = 0; -                rsp.volname = ""; -                if (err_str[0] == '\0') -                        snprintf (err_str, sizeof (err_str), "Operation failed"); -                rsp.op_errstr = err_str; -                cli_rsp = &rsp; -                glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL, -                                      gf_xdr_serialize_cli_add_brick_rsp, -                                      (xdrproc_t)xdr_gf1_cli_add_brick_rsp); -                ret = 0; //sent error to cli, prevent second reply -        } - -        glusterd_friend_sm (); -        glusterd_op_sm (); - -        if (free_ptr) -                GF_FREE (free_ptr); -        glusterd_volume_brickinfos_delete (&tmpvolinfo); -        if (brickinfo) -                glusterd_brickinfo_delete (brickinfo); -        if (cli_req.volname) -                free (cli_req.volname); //its malloced by xdr - -        return ret; -} - -int -glusterd_handle_replace_brick (rpcsvc_request_t *req) -{ -        int32_t                         ret = -1; -        gf1_cli_replace_brick_req          cli_req = {0,}; -        dict_t                          *dict = NULL; -        char                            *src_brick = NULL; -        char                            *dst_brick = NULL; -        int32_t                         op = 0; -        char                            operation[256]; -        glusterd_op_t                   cli_op = GD_OP_REPLACE_BRICK; - -        GF_ASSERT (req); - -        if (!gf_xdr_to_cli_replace_brick_req (req->msg[0], &cli_req)) { -                //failed to decode msg; -                req->rpc_err = GARBAGE_ARGS; -                goto out; -        } - -        gf_log ("glusterd", GF_LOG_INFO, "Received replace brick req"); - -        if (cli_req.bricks.bricks_len) { -                /* Unserialize the dictionary */ -                dict  = dict_new (); - -                ret = dict_unserialize (cli_req.bricks.bricks_val, -                                        cli_req.bricks.bricks_len, -                                        &dict); -                if (ret < 0) { -                        gf_log ("glusterd", GF_LOG_ERROR, -                                "failed to " -                                "unserialize req-buffer to dictionary"); -                        goto out; -                } else { -                        dict->extra_stdfree = cli_req.bricks.bricks_val; -                } -        } - -        ret = dict_get_int32 (dict, "operation", &op); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "dict_get on operation failed"); -                goto out; -        } - -        ret = dict_get_str (dict, "src-brick", &src_brick); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); -                goto out; -        } -        gf_log ("", GF_LOG_DEBUG, -                "src brick=%s", src_brick); - -        ret = dict_get_str (dict, "dst-brick", &dst_brick); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get dest brick"); -                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",cli_req.volname, src_brick, dst_brick -                    ,operation); - -        ret = glusterd_op_begin (req, GD_OP_REPLACE_BRICK, dict); -        gf_cmd_log ("Volume replace-brick","on volname: %s %s", cli_req.volname, -                   (ret) ? "FAILED" : "SUCCESS"); - -out: -        if (ret && dict) -                dict_unref (dict); -        if (cli_req.volname) -                free (cli_req.volname);//malloced by xdr - -        glusterd_friend_sm (); -        glusterd_op_sm (); - -        if (ret) -                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, -                                                     NULL, "operation failed"); - -        return ret; -} - -  int @@ -1583,205 +910,6 @@ out:          return ret;  } -int -glusterd_handle_gsync_set (rpcsvc_request_t *req) -{ -        int32_t                 ret     = 0; -        dict_t                  *dict   = NULL; -        gf1_cli_gsync_set_req   cli_req = {{0},}; -        glusterd_op_t           cli_op = GD_OP_GSYNC_SET; -        char                    *master = NULL; -        char                    *slave = NULL; -        char                    operation[256] = {0,}; -        int                     type = 0; -        glusterd_conf_t         *priv   = NULL; -        char                    *host_uuid = NULL; - -        GF_ASSERT (req); -        GF_ASSERT (THIS); -        GF_ASSERT (THIS->private); - -        priv = THIS->private; - -        if (!gf_xdr_to_cli_gsync_set_req (req->msg[0], &cli_req)) { -                req->rpc_err = GARBAGE_ARGS; -                goto out; -        } - -        if (cli_req.dict.dict_len) { -                dict = dict_new (); -                if (!dict) -                        goto out; - -                ret = dict_unserialize (cli_req.dict.dict_val, -                                        cli_req.dict.dict_len, -                                        &dict); -                if (ret < 0) { -                        gf_log ("glusterd", GF_LOG_ERROR, "failed to " -                                "unserialize req-buffer to dictionary"); -                        goto out; -                } else { -                        dict->extra_stdfree = cli_req.dict.dict_val; -                } - -                host_uuid = gf_strdup (uuid_utoa(priv->uuid)); -                if (host_uuid == NULL) { -                        gf_log ("glusterd", GF_LOG_ERROR, "failed to get" -                                "the uuid of the host machine"); -                        ret = -1; -                        goto out; -                } -                ret = dict_set_dynstr (dict, "host-uuid", host_uuid); -                if (ret) -                        goto out; - -        } - -        ret = dict_get_str (dict, "master", &master); -        if (ret < 0) { -                gf_log ("", GF_LOG_INFO, "master not found, while handling" -                         GEOREP" options"); -                master = "(No Master)"; -        } - -        ret = dict_get_str (dict, "slave", &slave); -        if (ret < 0) { -                gf_log ("", GF_LOG_INFO, "slave not not found, while" -                        "handling "GEOREP" options"); -                slave = "(No Slave)"; -        } - -        ret = dict_get_int32 (dict, "type", &type); -        if (ret < 0) { -                gf_log ("", GF_LOG_WARNING, "command type not found, while" -                        "handling "GEOREP" options"); -                goto out; -        } - -        switch (type) { - -        case GF_GSYNC_OPTION_TYPE_START: -                strncpy (operation, "start", sizeof (operation)); -                break; - -        case GF_GSYNC_OPTION_TYPE_STOP: -                strncpy (operation, "stop", sizeof (operation)); -                break; - -        case GF_GSYNC_OPTION_TYPE_CONFIG: -                strncpy (operation, "config", sizeof (operation)); -                break; - -        case GF_GSYNC_OPTION_TYPE_STATUS: -                strncpy (operation, "status", sizeof (operation)); -                break; -        } - -        gf_cmd_log ("volume "GEOREP, " %s command on %s,%s", operation, master, -                    slave); -        ret = glusterd_op_begin (req, GD_OP_GSYNC_SET, dict); -        gf_cmd_log ("volume "GEOREP, " %s command on %s,%s %s  ", operation, -                    master, slave, (ret != 0)? "FAILED" : "SUCCEEDED"); - -out: -        glusterd_friend_sm (); -        glusterd_op_sm (); - -        if (ret) { -                if (dict) -                        dict_unref (dict); -                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, -                                                     NULL, "operation failed"); -        } -        return ret; -} - -int -glusterd_handle_quota (rpcsvc_request_t *req) -{ -        int32_t                         ret = -1; -        gf1_cli_quota_req               cli_req = {0,}; -        dict_t                         *dict = NULL; -        glusterd_op_t                   cli_op = GD_OP_QUOTA; -        char                            operation[256] = {0, }; -        char                           *volname = NULL; -        int32_t                         type = 0; - -        GF_ASSERT (req); - -        if (!gf_xdr_to_cli_quota_req (req->msg[0], &cli_req)) { -                //failed to decode msg; -                req->rpc_err = GARBAGE_ARGS; -                goto out; -        } - -        if (cli_req.dict.dict_len) { -                /* Unserialize the dictionary */ -                dict  = dict_new (); - -                ret = dict_unserialize (cli_req.dict.dict_val, -                                        cli_req.dict.dict_len, -                                        &dict); -                if (ret < 0) { -                        gf_log ("glusterd", GF_LOG_ERROR, "failed to " -                                    "unserialize req-buffer to dictionary"); -                        goto out; -                } else { -                        dict->extra_stdfree = cli_req.dict.dict_val; -                } -        } - -        ret = dict_get_str (dict, "volname", &volname); -        if (ret) { -                gf_log ("", GF_LOG_WARNING, "Unable to get volume name, while" -                        "handling quota command"); -                goto out; -        } - -        ret = dict_get_int32 (dict, "type", &type); -        if (ret) { -                gf_log ("", GF_LOG_WARNING, "Unable to get type of cmd. , while" -                        "handling quota command"); -                goto out; -        } - -        switch (type) { -        case GF_QUOTA_OPTION_TYPE_ENABLE: -                strncpy (operation, "enable", sizeof (operation)); -                break; - -        case GF_QUOTA_OPTION_TYPE_DISABLE: -                strncpy (operation, "disable", sizeof (operation)); -                break; - -        case GF_QUOTA_OPTION_TYPE_LIMIT_USAGE: -                strncpy (operation, "limit-usage", sizeof (operation)); -                break; - -        case GF_QUOTA_OPTION_TYPE_REMOVE: -                strncpy (operation, "remove", sizeof (operation)); -                break; -        } -        gf_cmd_log ("volume quota", " %s command on %s", operation, volname); -        ret = glusterd_op_begin (req, GD_OP_QUOTA, dict); -        gf_cmd_log ("volume quota", " %s command on %s %s", operation,volname, -                    (ret != 0)? "FAILED" : "SUCCEEDED"); - -out: -        glusterd_friend_sm (); -        glusterd_op_sm (); - -        if (ret) { -                if (dict) -                        dict_unref (dict); -                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, -                                                     NULL, "operation failed"); -        } -        if (cli_req.volname) -                free (cli_req.volname); //malloced by xdr - -        return ret; -}  int  glusterd_handle_set_volume (rpcsvc_request_t *req) @@ -1867,457 +995,6 @@ out:  }  int -glusterd_handle_remove_brick (rpcsvc_request_t *req) -{ -        int32_t                         ret = -1; -        gf1_cli_remove_brick_req        cli_req = {0,}; -        dict_t                          *dict = NULL; -        int32_t                         count = 0; -        char                            *brick = NULL; -        char                            key[256] = {0,}; -        char                            *brick_list = NULL; -        int                             i = 1; -        glusterd_volinfo_t              *volinfo = NULL; -        glusterd_brickinfo_t            *brickinfo = NULL; -        int32_t                         pos = 0; -        int32_t                         sub_volume = 0; -        int32_t                         sub_volume_start = 0; -        int32_t                         sub_volume_end = 0; -        glusterd_brickinfo_t            *tmp = NULL; -        char                            err_str[2048] = {0}; -        gf1_cli_remove_brick_rsp        rsp = {0,}; -        void                            *cli_rsp = NULL; -        char                            vol_type[256] = {0,}; - -        GF_ASSERT (req); - -        if (!gf_xdr_to_cli_remove_brick_req (req->msg[0], &cli_req)) { -                //failed to decode msg; -                req->rpc_err = GARBAGE_ARGS; -                goto out; -        } - -        gf_cmd_log ("Volume remove-brick","on volname: %s attempted",cli_req.volname); -        gf_log ("glusterd", GF_LOG_INFO, "Received rem brick req"); - -        if (cli_req.bricks.bricks_len) { -                /* Unserialize the dictionary */ -                dict  = dict_new (); - -                ret = dict_unserialize (cli_req.bricks.bricks_val, -                                        cli_req.bricks.bricks_len, -                                        &dict); -                if (ret < 0) { -                        gf_log ("glusterd", GF_LOG_ERROR, -                                "failed to " -                                "unserialize req-buffer to dictionary"); -                        goto out; -                } else { -                        dict->extra_stdfree = cli_req.bricks.bricks_val; -                } -        } - -        ret = dict_get_int32 (dict, "count", &count); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get count"); -                goto out; -        } - -        ret = glusterd_volinfo_find (cli_req.volname, &volinfo); -        if (ret) { -                 snprintf (err_str, 2048, "Volume %s does not exist", -                          cli_req.volname); -                 gf_log ("", GF_LOG_ERROR, "%s", err_str); -                 goto out; -        } - -        if (volinfo->type == GF_CLUSTER_TYPE_REPLICATE) -                strcpy (vol_type, "replica"); -        else if (volinfo->type == GF_CLUSTER_TYPE_STRIPE) -                strcpy (vol_type, "stripe"); -        else -                strcpy (vol_type, "distribute"); - -	/* Do not allow remove-brick if the volume is plain stripe */ -	if ((volinfo->type == GF_CLUSTER_TYPE_STRIPE) && (volinfo->brick_count == volinfo->sub_count)) { -                snprintf (err_str, 2048, "Removing brick from a plain stripe is not allowed"); -                gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); -                ret = -1; -                goto out; -	} - -	/* Do not allow remove-brick if the bricks given is less than the replica count -	   or stripe count */ -        if (((volinfo->type == GF_CLUSTER_TYPE_REPLICATE) || (volinfo->type == GF_CLUSTER_TYPE_STRIPE)) -	    && !(volinfo->brick_count <= volinfo->sub_count)) { -                if (volinfo->sub_count && (count % volinfo->sub_count != 0)) { -                        snprintf (err_str, 2048, "Remove brick incorrect" -                                  " brick count of %d for %s %d", -                                  count, vol_type, volinfo->sub_count); -                        gf_log ("", GF_LOG_ERROR, "%s", err_str); -                        ret = -1; -                        goto out; -                } -        } - -        brick_list = GF_MALLOC (120000 * sizeof(*brick_list),gf_common_mt_char); - -        if (!brick_list) { -                ret = -1; -                goto out; -        } - -        strcpy (brick_list, " "); -        while ( i <= count) { -                snprintf (key, 256, "brick%d", i); -                ret = dict_get_str (dict, key, &brick); -                if (ret) { -                        gf_log ("", GF_LOG_ERROR, "Unable to get %s", key); -                        goto out; -                } -                gf_log ("", GF_LOG_DEBUG, "Remove brick count %d brick: %s", -                        i, brick); - -                ret = glusterd_volume_brickinfo_get_by_brick(brick, volinfo, &brickinfo); -                if (ret) { -                        snprintf(err_str, 2048,"Incorrect brick %s for volume" -                                " %s", brick, cli_req.volname); -                        gf_log ("", GF_LOG_ERROR, "%s", err_str); -                        goto out; -                } -                strcat(brick_list, brick); -                strcat(brick_list, " "); - -                i++; -                if ((volinfo->type == GF_CLUSTER_TYPE_NONE) || -                    (volinfo->brick_count <= volinfo->sub_count)) -                        continue; - -                pos = 0; -                list_for_each_entry (tmp, &volinfo->bricks, brick_list) { - -                        if ((!strcmp (tmp->hostname,brickinfo->hostname)) && -                            !strcmp (tmp->path, brickinfo->path)) { -                                gf_log ("", GF_LOG_INFO, "Found brick"); -                                if (!sub_volume && volinfo->sub_count) { -                                        sub_volume = (pos / volinfo-> -                                                      sub_count) + 1; -                                        sub_volume_start = volinfo->sub_count * -                                                           (sub_volume - 1); -                                        sub_volume_end = (volinfo->sub_count * -                                                          sub_volume) -1 ; -                                } else { -                                        if (pos < sub_volume_start || -                                            pos >sub_volume_end) { -                                                ret = -1; -                                                snprintf(err_str, 2048,"Bricks" -                                                         " not from same subvol" -                                                         " for %s", vol_type); -                                                gf_log ("",GF_LOG_ERROR, -                                                        "%s", err_str); -                                                goto out; -                                        } -                                } -                                break; -                        } -                        pos++; -                } -        } -        gf_cmd_log ("Volume remove-brick","volname: %s count:%d bricks:%s", -                    cli_req.volname, count, brick_list); - -        ret = glusterd_op_begin (req, GD_OP_REMOVE_BRICK, dict); -        gf_cmd_log ("Volume remove-brick","on volname: %s %s",cli_req.volname, -                    (ret) ? "FAILED" : "SUCCESS"); - -out: -        if (ret) { -                if (dict) -                        dict_unref (dict); -                rsp.op_ret = -1; -                rsp.op_errno = 0; -                rsp.volname = ""; -                if (err_str[0] == '\0') -                        snprintf (err_str, sizeof (err_str), "Operation failed"); -                gf_log ("", GF_LOG_ERROR, "%s", err_str); -                rsp.op_errstr = err_str; -                cli_rsp = &rsp; -                glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL, -                                      gf_xdr_serialize_cli_remove_brick_rsp, -                                      (xdrproc_t)xdr_gf1_cli_remove_brick_rsp); - -                ret = 0; //sent error to cli, prevent second reply - -        } -        if (brick_list) -                GF_FREE (brick_list); -        if (cli_req.volname) -                free (cli_req.volname); //its malloced by xdr - -        glusterd_friend_sm (); -        glusterd_op_sm (); - -        return ret; -} - -int -glusterd_handle_log_filename (rpcsvc_request_t *req) -{ -        int32_t                   ret     = -1; -        gf1_cli_log_filename_req  cli_req = {0,}; -        dict_t                   *dict    = NULL; -        glusterd_op_t             cli_op = GD_OP_LOG_FILENAME; - -        GF_ASSERT (req); - -        if (!gf_xdr_to_cli_log_filename_req (req->msg[0], &cli_req)) { -                //failed to decode msg; -                req->rpc_err = GARBAGE_ARGS; -                goto out; -        } - -        gf_log ("glusterd", GF_LOG_INFO, "Received log filename req " -                "for volume %s", cli_req.volname); - -        dict = dict_new (); -        if (!dict) -                goto out; - -        ret = dict_set_dynmstr (dict, "volname", cli_req.volname); -        if (ret) -                goto out; -        ret = dict_set_dynmstr (dict, "brick", cli_req.brick); -        if (ret) -                goto out; -        ret = dict_set_dynmstr (dict, "path", cli_req.path); -        if (ret) -                goto out; - -        ret = glusterd_op_begin (req, GD_OP_LOG_FILENAME, dict); - -out: -        if (ret && dict) -                dict_unref (dict); - -        glusterd_friend_sm (); -        glusterd_op_sm (); - -        if (ret) -                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, -                                                     NULL, "operation failed"); - -        return ret; -} - -int -glusterd_handle_log_locate (rpcsvc_request_t *req) -{ -        int32_t                 ret     = -1; -        gf1_cli_log_locate_req  cli_req = {0,}; -        gf1_cli_log_locate_rsp  rsp     = {0,}; -        glusterd_conf_t        *priv = NULL; -        glusterd_volinfo_t     *volinfo = NULL; -        glusterd_brickinfo_t   *brickinfo = NULL; -        char                    tmp_str[PATH_MAX] = {0,}; -        char                   *tmp_brick = NULL; -        uint32_t                found = 0; -        glusterd_brickinfo_t   *tmpbrkinfo = NULL; - -        GF_ASSERT (req); - -        priv    = THIS->private; - -        if (!gf_xdr_to_cli_log_locate_req (req->msg[0], &cli_req)) { -                //failed to decode msg; -                req->rpc_err = GARBAGE_ARGS; -                goto out; -        } - -        gf_log ("glusterd", GF_LOG_INFO, "Received log locate req " -                "for volume %s", cli_req.volname); - -        if (strchr (cli_req.brick, ':')) { -                /* TODO: need to get info of only that brick and then -                   tell what is the exact location */ -                tmp_brick = gf_strdup (cli_req.brick); -                if (!tmp_brick) -                        goto out; - -                gf_log ("", GF_LOG_DEBUG, "brick : %s", cli_req.brick); -                ret = glusterd_brickinfo_from_brick (tmp_brick, &tmpbrkinfo); -                if (ret) { -                        gf_log ("glusterd", GF_LOG_ERROR, -                                "Cannot get brickinfo from the brick"); -                        goto out; -                } -        } - -        ret = glusterd_volinfo_find (cli_req.volname, &volinfo); -        if (ret) { -                rsp.path = "request sent on non-existent volume"; -                goto out; -        } - -        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { -                if (tmpbrkinfo) { -                        ret = glusterd_resolve_brick (tmpbrkinfo); -                        if (ret) { -                                gf_log ("glusterd", GF_LOG_ERROR, -                                        "cannot resolve the brick"); -                                goto out; -                        } -                        if (uuid_compare (tmpbrkinfo->uuid, brickinfo->uuid) || strcmp (brickinfo->path, tmpbrkinfo->path)) -                                continue; -                } - -                if (brickinfo->logfile) { -                        strcpy (tmp_str, brickinfo->logfile); -                        rsp.path = dirname (tmp_str); -                        found = 1; -                } else { -                        snprintf (tmp_str, PATH_MAX, "%s/bricks/", -                                  DEFAULT_LOG_FILE_DIRECTORY); -                        rsp.path = tmp_str; -                        found = 1; -                } -                break; -        } - -        if (!found) { -                snprintf (tmp_str, PATH_MAX, "brick %s:%s does not exitst in the volume %s", -                          tmpbrkinfo->hostname, tmpbrkinfo->path, cli_req.volname); -                rsp.path = tmp_str; -        } - -        ret = 0; -out: -        if (tmp_brick) -                GF_FREE (tmp_brick); -        if (tmpbrkinfo) -                glusterd_brickinfo_delete (tmpbrkinfo); -        rsp.op_ret = ret; -        if (!rsp.path) -                rsp.path = "Operation failed"; - -        ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL, -                                     gf_xdr_serialize_cli_log_locate_rsp, -                                     (xdrproc_t)xdr_gf1_cli_log_locate_rsp); - -        if (cli_req.brick) -                free (cli_req.brick); //its malloced by xdr -        if (cli_req.volname) -                free (cli_req.volname); //its malloced by xdr - -        glusterd_friend_sm (); -        glusterd_op_sm (); - -        return ret; -} - -int -glusterd_handle_log_level (rpcsvc_request_t *req) -{ -        int32_t                ret       = -1; -        dict_t                *dict      = NULL; -        gf1_cli_log_level_req  cli_req   = {0,}; -        glusterd_op_t         cli_op    = GD_OP_LOG_LEVEL; - -        GF_ASSERT(req); - - -        if (!gf_xdr_to_cli_log_level_req(req->msg[0], &cli_req)) { -                gf_log ("glusterd", GF_LOG_ERROR, "Failed to decode rpc message"); -                req->rpc_err = GARBAGE_ARGS; -                goto out; -        } - -        gf_log ("glusterd", GF_LOG_DEBUG, "Got log level request for: Volume [%s]" -                " Xlator [%s] LogLevel [\"%s\"]", cli_req.volname, cli_req.xlator, cli_req.loglevel); - -        dict = dict_new (); -        if (!dict) -                goto out; - -        ret = dict_set_dynmstr (dict, "volname", cli_req.volname); -        if (ret) -                goto out; - -        ret = dict_set_dynmstr (dict, "xlator", cli_req.xlator); -        if (ret) -                goto out; - -        ret = dict_set_dynmstr (dict, "loglevel", cli_req.loglevel); -        if (ret) -                goto out; - -        ret = glusterd_op_begin (req, cli_op, dict); - - out: -        if (ret && dict) -                dict_unref (dict); - -        glusterd_friend_sm(); -        glusterd_op_sm(); - -        if (ret) -                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, NULL, -                                                     "Operation failed"); - -        return ret; -} - -int -glusterd_handle_log_rotate (rpcsvc_request_t *req) -{ -        int32_t                 ret     = -1; -        gf1_cli_log_rotate_req  cli_req = {0,}; -        dict_t                 *dict    = NULL; -        glusterd_op_t           cli_op = GD_OP_LOG_ROTATE; - -        GF_ASSERT (req); - -        if (!gf_xdr_to_cli_log_rotate_req (req->msg[0], &cli_req)) { -                //failed to decode msg; -                req->rpc_err = GARBAGE_ARGS; -                goto out; -        } - -        gf_log ("glusterd", GF_LOG_INFO, "Received log rotate req " -                "for volume %s", cli_req.volname); - -        dict = dict_new (); -        if (!dict) -                goto out; - -        ret = dict_set_dynmstr (dict, "volname", cli_req.volname); -        if (ret) -                goto out; - -        ret = dict_set_dynmstr (dict, "brick", cli_req.brick); -        if (ret) -                goto out; - -        ret = dict_set_uint64 (dict, "rotate-key", (uint64_t)time (NULL)); -        if (ret) -                goto out; - -        ret = glusterd_op_begin (req, GD_OP_LOG_ROTATE, dict); - -out: -        if (ret && dict) -                dict_unref (dict); - -        glusterd_friend_sm (); -        glusterd_op_sm (); - -        if (ret) -                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, -                                                     NULL, "operation failed"); - -        return ret; -} - -int  glusterd_handle_sync_volume (rpcsvc_request_t *req)  {          int32_t                          ret     = -1; diff --git a/xlators/mgmt/glusterd/src/glusterd-log-ops.c b/xlators/mgmt/glusterd/src/glusterd-log-ops.c new file mode 100644 index 000000000..017698291 --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-log-ops.c @@ -0,0 +1,804 @@ +/* +  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/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "cli1.h" +#include "glusterd.h" +#include "glusterd-op-sm.h" +#include "glusterd-store.h" +#include "glusterd-utils.h" +#include "glusterd-volgen.h" + +#include <signal.h> + +int +glusterd_handle_log_filename (rpcsvc_request_t *req) +{ +        int32_t                   ret     = -1; +        gf1_cli_log_filename_req  cli_req = {0,}; +        dict_t                   *dict    = NULL; +        glusterd_op_t             cli_op = GD_OP_LOG_FILENAME; + +        GF_ASSERT (req); + +        if (!gf_xdr_to_cli_log_filename_req (req->msg[0], &cli_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        gf_log ("glusterd", GF_LOG_INFO, "Received log filename req " +                "for volume %s", cli_req.volname); + +        dict = dict_new (); +        if (!dict) +                goto out; + +        ret = dict_set_dynmstr (dict, "volname", cli_req.volname); +        if (ret) +                goto out; +        ret = dict_set_dynmstr (dict, "brick", cli_req.brick); +        if (ret) +                goto out; +        ret = dict_set_dynmstr (dict, "path", cli_req.path); +        if (ret) +                goto out; + +        ret = glusterd_op_begin (req, GD_OP_LOG_FILENAME, dict); + +out: +        if (ret && dict) +                dict_unref (dict); + +        glusterd_friend_sm (); +        glusterd_op_sm (); + +        if (ret) +                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, +                                                     NULL, "operation failed"); + +        return ret; +} + +int +glusterd_handle_log_locate (rpcsvc_request_t *req) +{ +        int32_t                 ret     = -1; +        gf1_cli_log_locate_req  cli_req = {0,}; +        gf1_cli_log_locate_rsp  rsp     = {0,}; +        glusterd_conf_t        *priv = NULL; +        glusterd_volinfo_t     *volinfo = NULL; +        glusterd_brickinfo_t   *brickinfo = NULL; +        char                    tmp_str[PATH_MAX] = {0,}; +        char                   *tmp_brick = NULL; +        uint32_t                found = 0; +        glusterd_brickinfo_t   *tmpbrkinfo = NULL; + +        GF_ASSERT (req); + +        priv    = THIS->private; + +        if (!gf_xdr_to_cli_log_locate_req (req->msg[0], &cli_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        gf_log ("glusterd", GF_LOG_INFO, "Received log locate req " +                "for volume %s", cli_req.volname); + +        if (strchr (cli_req.brick, ':')) { +                /* TODO: need to get info of only that brick and then +                   tell what is the exact location */ +                tmp_brick = gf_strdup (cli_req.brick); +                if (!tmp_brick) +                        goto out; + +                gf_log ("", GF_LOG_DEBUG, "brick : %s", cli_req.brick); +                ret = glusterd_brickinfo_from_brick (tmp_brick, &tmpbrkinfo); +                if (ret) { +                        gf_log ("glusterd", GF_LOG_ERROR, +                                "Cannot get brickinfo from the brick"); +                        goto out; +                } +        } + +        ret = glusterd_volinfo_find (cli_req.volname, &volinfo); +        if (ret) { +                rsp.path = "request sent on non-existent volume"; +                goto out; +        } + +        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { +                if (tmpbrkinfo) { +                        ret = glusterd_resolve_brick (tmpbrkinfo); +                        if (ret) { +                                gf_log ("glusterd", GF_LOG_ERROR, +                                        "cannot resolve the brick"); +                                goto out; +                        } +                        if (uuid_compare (tmpbrkinfo->uuid, brickinfo->uuid) || strcmp (brickinfo->path, tmpbrkinfo->path)) +                                continue; +                } + +                if (brickinfo->logfile) { +                        strcpy (tmp_str, brickinfo->logfile); +                        rsp.path = dirname (tmp_str); +                        found = 1; +                } else { +                        snprintf (tmp_str, PATH_MAX, "%s/bricks/", +                                  DEFAULT_LOG_FILE_DIRECTORY); +                        rsp.path = tmp_str; +                        found = 1; +                } +                break; +        } + +        if (!found) { +                snprintf (tmp_str, PATH_MAX, "brick %s:%s does not exitst in the volume %s", +                          tmpbrkinfo->hostname, tmpbrkinfo->path, cli_req.volname); +                rsp.path = tmp_str; +        } + +        ret = 0; +out: +        if (tmp_brick) +                GF_FREE (tmp_brick); +        if (tmpbrkinfo) +                glusterd_brickinfo_delete (tmpbrkinfo); +        rsp.op_ret = ret; +        if (!rsp.path) +                rsp.path = "Operation failed"; + +        ret = glusterd_submit_reply (req, &rsp, NULL, 0, NULL, +                                     gf_xdr_serialize_cli_log_locate_rsp, +                                     (xdrproc_t)xdr_gf1_cli_log_locate_rsp); + +        if (cli_req.brick) +                free (cli_req.brick); //its malloced by xdr +        if (cli_req.volname) +                free (cli_req.volname); //its malloced by xdr + +        glusterd_friend_sm (); +        glusterd_op_sm (); + +        return ret; +} + +int +glusterd_handle_log_level (rpcsvc_request_t *req) +{ +        int32_t                ret       = -1; +        dict_t                *dict      = NULL; +        gf1_cli_log_level_req  cli_req   = {0,}; +        glusterd_op_t         cli_op    = GD_OP_LOG_LEVEL; + +        GF_ASSERT(req); + + +        if (!gf_xdr_to_cli_log_level_req(req->msg[0], &cli_req)) { +                gf_log ("glusterd", GF_LOG_ERROR, "Failed to decode rpc message"); +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        gf_log ("glusterd", GF_LOG_DEBUG, "Got log level request for: Volume [%s]" +                " Xlator [%s] LogLevel [\"%s\"]", cli_req.volname, cli_req.xlator, cli_req.loglevel); + +        dict = dict_new (); +        if (!dict) +                goto out; + +        ret = dict_set_dynmstr (dict, "volname", cli_req.volname); +        if (ret) +                goto out; + +        ret = dict_set_dynmstr (dict, "xlator", cli_req.xlator); +        if (ret) +                goto out; + +        ret = dict_set_dynmstr (dict, "loglevel", cli_req.loglevel); +        if (ret) +                goto out; + +        ret = glusterd_op_begin (req, cli_op, dict); + + out: +        if (ret && dict) +                dict_unref (dict); + +        glusterd_friend_sm(); +        glusterd_op_sm(); + +        if (ret) +                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, NULL, +                                                     "Operation failed"); + +        return ret; +} + +int +glusterd_handle_log_rotate (rpcsvc_request_t *req) +{ +        int32_t                 ret     = -1; +        gf1_cli_log_rotate_req  cli_req = {0,}; +        dict_t                 *dict    = NULL; +        glusterd_op_t           cli_op = GD_OP_LOG_ROTATE; + +        GF_ASSERT (req); + +        if (!gf_xdr_to_cli_log_rotate_req (req->msg[0], &cli_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        gf_log ("glusterd", GF_LOG_INFO, "Received log rotate req " +                "for volume %s", cli_req.volname); + +        dict = dict_new (); +        if (!dict) +                goto out; + +        ret = dict_set_dynmstr (dict, "volname", cli_req.volname); +        if (ret) +                goto out; + +        ret = dict_set_dynmstr (dict, "brick", cli_req.brick); +        if (ret) +                goto out; + +        ret = dict_set_uint64 (dict, "rotate-key", (uint64_t)time (NULL)); +        if (ret) +                goto out; + +        ret = glusterd_op_begin (req, GD_OP_LOG_ROTATE, dict); + +out: +        if (ret && dict) +                dict_unref (dict); + +        glusterd_friend_sm (); +        glusterd_op_sm (); + +        if (ret) +                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, +                                                     NULL, "operation failed"); + +        return ret; +} + +/* op-sm */ +int +glusterd_op_stage_log_filename (dict_t *dict, char **op_errstr) +{ +        int                                     ret = -1; +        char                                    *volname = NULL; +        gf_boolean_t                            exists = _gf_false; +        char                                    msg[2048] = {0}; +        char                                    *path = NULL; +        char                                    hostname[2048] = {0}; +        char                                    *brick = NULL; +        glusterd_volinfo_t                      *volinfo = NULL; + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        exists = glusterd_check_volume_exists (volname); +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (!exists || ret) { +                snprintf (msg, sizeof (msg), "Volume %s does not exist", +                          volname); +                gf_log ("", GF_LOG_ERROR, "%s", msg); +                *op_errstr = gf_strdup (msg); +                ret = -1; +                goto out; +        } + +        ret = dict_get_str (dict, "brick", &brick); +        if (ret) +                goto out; + +        if (strchr (brick, ':')) { +                ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, +                                                              NULL); +                if (ret) { +                        snprintf (msg, sizeof (msg), "Incorrect brick %s " +                                  "for volume %s", brick, volname); +                        gf_log ("", GF_LOG_ERROR, "%s", msg); +                        *op_errstr = gf_strdup (msg); +                        goto out; +                } +        } + +        ret = dict_get_str (dict, "path", &path); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "path not found"); +                goto out; +        } + +        ret = gethostname (hostname, sizeof (hostname)); +        if (ret) { +                snprintf (msg, sizeof (msg), "Failed to get hostname, error:%s", +                strerror (errno)); +                gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); +                *op_errstr = gf_strdup (msg); +                goto out; +        } + +        ret = glusterd_brick_create_path (hostname, path, volinfo->volume_id, +                                          0777, op_errstr); +        if (ret) +                goto out; +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +        return ret; +} + +int +glusterd_op_stage_log_rotate (dict_t *dict, char **op_errstr) +{ +        int                                     ret = -1; +        char                                    *volname = NULL; +        glusterd_volinfo_t                      *volinfo = NULL; +        gf_boolean_t                            exists = _gf_false; +        char                                    msg[2048] = {0}; +        char                                    *brick = NULL; + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        exists = glusterd_check_volume_exists (volname); +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (!exists) { +                snprintf (msg, sizeof (msg), "Volume %s does not exist", +                          volname); +                gf_log ("", GF_LOG_ERROR, "%s", msg); +                *op_errstr = gf_strdup (msg); +                ret = -1; +                goto out; +        } + +        if (_gf_false == glusterd_is_volume_started (volinfo)) { +                snprintf (msg, sizeof (msg), "Volume %s needs to be started before" +                          " log rotate.", volname); +                gf_log ("", GF_LOG_ERROR, "%s", msg); +                *op_errstr = gf_strdup (msg); +                ret = -1; +                goto out; +        } + +        ret = dict_get_str (dict, "brick", &brick); +        if (ret) +                goto out; + +        if (strchr (brick, ':')) { +                ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, +                                                              NULL); +                if (ret) { +                        snprintf (msg, sizeof (msg), "Incorrect brick %s " +                                  "for volume %s", brick, volname); +                        gf_log ("", GF_LOG_ERROR, "%s", msg); +                        *op_errstr = gf_strdup (msg); +                        goto out; +                } +        } +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +        return ret; +} + +int +glusterd_op_stage_log_level (dict_t *dict, char **op_errstr) +{ +        int                 ret            = -1; +        gf_boolean_t        exists         = _gf_false; +        dict_t             *val_dict       = NULL; +        char               *volname        = NULL; +        char               *xlator         = NULL; +        char               *loglevel       = NULL; +        glusterd_volinfo_t *volinfo        = NULL; +        glusterd_conf_t    *priv           = NULL; +        xlator_t           *this           = NULL; +        char msg[2048]                     = {0,}; + +        GF_ASSERT (dict); +        this = THIS; +        GF_ASSERT (this); +        priv = this->private; +        GF_ASSERT(priv); + +        val_dict = dict_new (); +        if (!val_dict) +                goto out; + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        /* +         * check for existence of the gieven volume +         */ +        exists = glusterd_check_volume_exists (volname); +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (!exists || ret) { +                snprintf (msg, sizeof(msg), "Volume %s does not exist", volname); +                gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); + +                *op_errstr = gf_strdup(msg); +                ret = -1; +                goto out; +        } + +        ret = dict_get_str (dict, "xlator", &xlator); +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, "Unable to get translator name"); +                goto out; +        } + +        ret = dict_get_str (dict, "loglevel", &loglevel); +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, "Unable to get loglevel"); +                goto out; +        } + +        ret = 0; + + out: +        if (val_dict) +                dict_unref (val_dict); + +        if (ret) { +                if (!(*op_errstr)) { +                        *op_errstr = gf_strdup ("Error, Validation Failed"); +                        gf_log ("glusterd", GF_LOG_DEBUG, "Error, Cannot Validate option: %s", +                                *op_errstr); +                } +        } + +        gf_log ("glusterd", GF_LOG_DEBUG, "Returning: %d", ret); +        return ret; +} + +int +glusterd_op_log_filename (dict_t *dict) +{ +        int                   ret                = -1; +        glusterd_conf_t      *priv               = NULL; +        glusterd_volinfo_t   *volinfo            = NULL; +        glusterd_brickinfo_t *brickinfo          = NULL; +        xlator_t             *this               = NULL; +        char                 *volname            = NULL; +        char                 *brick              = NULL; +        char                 *path               = NULL; +        char                  logfile[PATH_MAX]  = {0,}; +        char                  exp_path[PATH_MAX] = {0,}; +        struct stat           stbuf              = {0,}; +        int                   valid_brick        = 0; +        glusterd_brickinfo_t *tmpbrkinfo         = NULL; +        char*                new_logdir         = NULL; + +        this = THIS; +        GF_ASSERT (this); +        priv = this->private; +        GF_ASSERT (priv); + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "volname not found"); +                goto out; +        } + +        ret = dict_get_str (dict, "path", &path); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "path not found"); +                goto out; +        } + +        ret = dict_get_str (dict, "brick", &brick); +        if (ret) +                goto out; + +        ret  = glusterd_volinfo_find (volname, &volinfo); +        if (ret) +                goto out; + +        if (!strchr (brick, ':')) { +                brick = NULL; +                ret = stat (path, &stbuf); +                if (ret || !S_ISDIR (stbuf.st_mode)) { +                        ret = -1; +                        gf_log ("", GF_LOG_ERROR, "not a directory"); +                        goto out; +                } +                new_logdir = gf_strdup (path); +                if (!new_logdir) { +                        ret = -1; +                        gf_log ("", GF_LOG_ERROR, "Out of memory"); +                        goto out; +                } +                if (volinfo->logdir) +                        GF_FREE (volinfo->logdir); +                volinfo->logdir = new_logdir; +        } else { +                ret = glusterd_brickinfo_from_brick (brick, &tmpbrkinfo); +                if (ret) { +                        gf_log ("glusterd", GF_LOG_ERROR, +                                "cannot get brickinfo from brick"); +                        goto out; +                } +        } + + +        ret = -1; +        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + +                if (uuid_is_null (brickinfo->uuid)) { +                        ret = glusterd_resolve_brick (brickinfo); +                        if (ret) +                                goto out; +                } + +                /* check if the brickinfo belongs to the 'this' machine */ +                if (uuid_compare (brickinfo->uuid, priv->uuid)) +                        continue; + +                if (brick && strcmp (tmpbrkinfo->path,brickinfo->path)) +                        continue; + +                valid_brick = 1; + +                /* If there are more than one brick in 'this' server, its an +                 * extra check, but it doesn't harm functionality +                 */ +                ret = stat (path, &stbuf); +                if (ret || !S_ISDIR (stbuf.st_mode)) { +                        ret = -1; +                        gf_log ("", GF_LOG_ERROR, "not a directory"); +                        goto out; +                } + +                GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, exp_path); + +                snprintf (logfile, PATH_MAX, "%s/%s.log", path, exp_path); + +                if (brickinfo->logfile) +                        GF_FREE (brickinfo->logfile); +                brickinfo->logfile = gf_strdup (logfile); +                ret = 0; + +                /* If request was for brick, only one iteration is enough */ +                if (brick) +                        break; +        } + +        if (ret && !valid_brick) +                ret = 0; +out: +        if (tmpbrkinfo) +                glusterd_brickinfo_delete (tmpbrkinfo); + +        return ret; +} + +int +glusterd_op_log_rotate (dict_t *dict) +{ +        int                   ret                = -1; +        glusterd_conf_t      *priv               = NULL; +        glusterd_volinfo_t   *volinfo            = NULL; +        glusterd_brickinfo_t *brickinfo          = NULL; +        xlator_t             *this               = NULL; +        char                 *volname            = NULL; +        char                 *brick              = NULL; +        char                  path[PATH_MAX]     = {0,}; +        char                  logfile[PATH_MAX]  = {0,}; +        char                  pidfile[PATH_MAX]  = {0,}; +        FILE                 *file               = NULL; +        pid_t                 pid                = 0; +        uint64_t              key                = 0; +        int                   valid_brick        = 0; +        glusterd_brickinfo_t *tmpbrkinfo         = NULL; + +        this = THIS; +        GF_ASSERT (this); +        priv = this->private; +        GF_ASSERT (priv); + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "volname not found"); +                goto out; +        } + +        ret = dict_get_uint64 (dict, "rotate-key", &key); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "rotate key not found"); +                goto out; +        } + +        ret = dict_get_str (dict, "brick", &brick); +        if (ret) +                goto out; + +        if (!strchr (brick, ':')) +                brick = NULL; +        else { +                ret = glusterd_brickinfo_from_brick (brick, &tmpbrkinfo); +                if (ret) { +                        gf_log ("glusterd", GF_LOG_ERROR, +                                "cannot get brickinfo from brick"); +                        goto out; +                } +        } + +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (ret) +                goto out; + +        ret = -1; +        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { +                if (uuid_compare (brickinfo->uuid, priv->uuid)) +                        continue; + +                if (brick && +                    (strcmp (tmpbrkinfo->hostname, brickinfo->hostname) || +                     strcmp (tmpbrkinfo->path,brickinfo->path))) +                        continue; + +                valid_brick = 1; + +                GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); +                GLUSTERD_GET_BRICK_PIDFILE (pidfile, path, brickinfo->hostname, +                                            brickinfo->path); + +                file = fopen (pidfile, "r+"); +                if (!file) { +                        gf_log ("", GF_LOG_ERROR, "Unable to open pidfile: %s", +                                pidfile); +                        ret = -1; +                        goto out; +                } + +                ret = fscanf (file, "%d", &pid); +                if (ret <= 0) { +                        gf_log ("", GF_LOG_ERROR, "Unable to read pidfile: %s", +                                pidfile); +                        ret = -1; +                        goto out; +                } +                fclose (file); +                file = NULL; + +                snprintf (logfile, PATH_MAX, "%s.%"PRIu64, +                          brickinfo->logfile, key); + +                ret = rename (brickinfo->logfile, logfile); +                if (ret) +                        gf_log ("", GF_LOG_WARNING, "rename failed"); + +                ret = kill (pid, SIGHUP); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, "Unable to SIGHUP to %d", pid); +                        goto out; +                } +                ret = 0; + +                /* If request was for brick, only one iteration is enough */ +                if (brick) +                        break; +        } + +        if (ret && !valid_brick) +                ret = 0; + +out: +        if (tmpbrkinfo) +                glusterd_brickinfo_delete (tmpbrkinfo); + +        return ret; +} + +int +glusterd_op_log_level (dict_t *dict) +{ +        int32_t             ret           = -1; +        glusterd_volinfo_t *volinfo       = NULL; +        char               *volname       = NULL; +        char               *xlator        = NULL; +        char               *loglevel      = NULL; +        xlator_t           *this          = NULL; +        glusterd_conf_t    *priv          = NULL; + +        this = THIS; +        GF_ASSERT (this); + +        priv = this->private; +        GF_ASSERT (priv); + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        ret = dict_get_str (dict, "xlator", &xlator); +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, "Unable to get translator name"); +                goto out; +        } + +        ret = dict_get_str (dict, "loglevel", &loglevel); +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, "Unable to get Loglevel to use"); +                goto out; +        } + +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Cannot find volume: %s", volname); +                goto out; +        } + +        xlator = gf_strdup (xlator); + +        ret = dict_set_dynstr (volinfo->dict, "xlator", xlator); +        if (ret) +                goto out; + +        loglevel = gf_strdup (loglevel); + +        ret = dict_set_dynstr (volinfo->dict, "loglevel", loglevel); +        if (ret) +                goto out; + +        ret = glusterd_create_volfiles_and_notify_services (volinfo); +        if (ret) { +                gf_log ("glusterd", GF_LOG_ERROR, "Unable to create volfile for command" +                        " 'log level'"); +                ret = -1; +                goto out; +        } + +        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); +        if (ret) +                goto out; + +        ret = 0; + + out: +        gf_log ("glusterd", GF_LOG_DEBUG, "(cli log level) Returning: %d", ret); +        return ret; +} + diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index a36d10b68..a460582a0 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -54,8 +54,6 @@  #include <sys/types.h>  #include <signal.h>  #include <sys/wait.h> -#define glusterd_op_start_volume_args_get(dict, volname, flags) \ -        glusterd_op_stop_volume_args_get (dict, volname, flags)  static struct list_head gd_op_sm_queue;  pthread_mutex_t       gd_op_sm_lock; @@ -98,13 +96,6 @@ static char *glusterd_op_sm_event_names[] = {          "GD_OP_EVENT_INVALID"  }; -static char *gsync_reserved_opts[] = { -        "gluster-command", -        "pid-file", -        "state-file", -        "session-owner", -        NULL -};  static int  glusterd_restart_brick_servers (glusterd_volinfo_t *); @@ -274,1048 +265,6 @@ out:          return ret;  } -static int -glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr) -{ -        int                                     ret = 0; -        char                                    *volname = NULL; -        gf_boolean_t                            exists = _gf_false; -        char                                    *bricks = NULL; -        char                                    *brick_list = NULL; -        char                                    *free_ptr = NULL; -        glusterd_brickinfo_t                    *brick_info = NULL; -        int32_t                                 brick_count = 0; -        int32_t                                 i = 0; -        char                                    *brick = NULL; -        char                                    *tmpptr = NULL; -        char                                    cmd_str[1024]; -        xlator_t                                *this = NULL; -        glusterd_conf_t                         *priv = NULL; -        char                                    msg[2048] = {0}; -        uuid_t                                  volume_uuid; -        char                                    *volume_uuid_str; - -        this = THIS; -        if (!this) { -                gf_log ("glusterd", GF_LOG_ERROR, -                        "this is NULL"); -                goto out; -        } - -        priv = this->private; -        if (!priv) { -                gf_log ("glusterd", GF_LOG_ERROR, -                        "priv is NULL"); -                goto out; -        } - -        ret = dict_get_str (dict, "volname", &volname); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        exists = glusterd_check_volume_exists (volname); - -        if (exists) { -                snprintf (msg, sizeof (msg), "Volume %s already exists", -                          volname); -                gf_log ("", GF_LOG_ERROR, "%s", msg); -                *op_errstr = gf_strdup (msg); -                ret = -1; -                goto out; -        } else { -                ret = 0; -        } -        ret = dict_get_int32 (dict, "count", &brick_count); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get count"); -                goto out; -        } -        ret = dict_get_str (dict, "volume-id", &volume_uuid_str); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume id"); -                goto out; -        } -        ret = uuid_parse (volume_uuid_str, volume_uuid); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to parse volume id"); -                goto out; -        } - -        ret = dict_get_str (dict, "bricks", &bricks); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); -                goto out; -        } - -        if (bricks) { -                brick_list = gf_strdup (bricks); -                if (!brick_list) { -                        ret = -1; -                        gf_log ("", GF_LOG_ERROR, "Out of memory"); -                        goto out; -                } else { -                        free_ptr = brick_list; -                } -        } - -        while ( i < brick_count) { -                i++; -                brick= strtok_r (brick_list, " \n", &tmpptr); -                brick_list = tmpptr; - -                if (!glusterd_store_is_valid_brickpath (volname, brick) || -                        !glusterd_is_valid_volfpath (volname, brick)) { -                        snprintf (msg, sizeof (msg), "brick path %s is too " -                                  "long.", brick); -                        gf_log ("", GF_LOG_ERROR, "%s", msg); -                        *op_errstr = gf_strdup (msg); - -                        ret = -1; -                        goto out; -                } - -                ret = glusterd_brickinfo_from_brick (brick, &brick_info); -                if (ret) -                        goto out; -                snprintf (cmd_str, 1024, "%s", brick_info->path); -                ret = glusterd_resolve_brick (brick_info); -                if (ret) { -                        gf_log ("glusterd", GF_LOG_ERROR, "cannot resolve " -                                "brick: %s:%s", brick_info->hostname, -                                brick_info->path); -                        goto out; -                } - -                if (!uuid_compare (brick_info->uuid, priv->uuid)) { -                        ret = glusterd_brick_create_path (brick_info->hostname, -                                                          brick_info->path, -                                                          volume_uuid, -                                                          0777, op_errstr); -                        if (ret) -                                goto out; -                        brick_list = tmpptr; -                } -                glusterd_brickinfo_delete (brick_info); -                brick_info = NULL; -        } -out: -        if (free_ptr) -                GF_FREE (free_ptr); -        if (brick_info) -                glusterd_brickinfo_delete (brick_info); -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - -        return ret; -} - -static int -glusterd_op_stop_volume_args_get (dict_t *dict, char** volname, -                                  int *flags) -{ -        int ret = -1; - -        if (!dict || !volname || !flags) -                goto out; - -        ret = dict_get_str (dict, "volname", volname); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        ret = dict_get_int32 (dict, "flags", flags); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get flags"); -                goto out; -        } -out: -        return ret; -} - -static int -glusterd_op_stage_start_volume (dict_t *dict, char **op_errstr) -{ -        int                                     ret = 0; -        char                                    *volname = NULL; -        int                                     flags = 0; -        gf_boolean_t                            exists = _gf_false; -        glusterd_volinfo_t                      *volinfo = NULL; -        glusterd_brickinfo_t                    *brickinfo = NULL; -        char                                    msg[2048]; -        glusterd_conf_t                         *priv = NULL; - -        priv = THIS->private; -        if (!priv) { -                gf_log ("glusterd", GF_LOG_ERROR, -                        "priv is NULL"); -                ret = -1; -                goto out; -        } - -        ret = glusterd_op_start_volume_args_get (dict, &volname, &flags); -        if (ret) -                goto out; - -        exists = glusterd_check_volume_exists (volname); - -        if (!exists) { -                snprintf (msg, sizeof (msg), "Volume %s does not exist", volname); -                gf_log ("", GF_LOG_ERROR, "%s", -                        msg); -                *op_errstr = gf_strdup (msg); -                ret = -1; -        } else { -                ret = 0; -        } - -        ret  = glusterd_volinfo_find (volname, &volinfo); - -        if (ret) -                goto out; - -        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { -                ret = glusterd_resolve_brick (brickinfo); -                if (ret) { -                        gf_log ("", GF_LOG_ERROR, -                                "Unable to resolve brick %s:%s", -                                brickinfo->hostname, brickinfo->path); -                        goto out; -                } - -                if (!uuid_compare (brickinfo->uuid, priv->uuid)) { -                        ret = glusterd_brick_create_path (brickinfo->hostname, -                                                          brickinfo->path, -                                                          volinfo->volume_id, -                                                          0777, op_errstr); -                        if (ret) -                                goto out; -                } - -                if (!(flags & GF_CLI_FLAG_OP_FORCE)) { -                        if (glusterd_is_volume_started (volinfo)) { -                                snprintf (msg, sizeof (msg), "Volume %s already" -                                          " started", volname); -                                gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); -                                *op_errstr = gf_strdup (msg); -                                ret = -1; -                                goto out; -                        } -                } -        } - -        ret = 0; -out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - -        return ret; -} - -static int -glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr) -{ -        int                                     ret = -1; -        char                                    *volname = NULL; -        int                                     flags = 0; -        gf_boolean_t                            exists = _gf_false; -        gf_boolean_t                            is_run = _gf_false; -        glusterd_volinfo_t                      *volinfo = NULL; -        char                                    msg[2048] = {0}; - - -        ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags); -        if (ret) -                goto out; - -        exists = glusterd_check_volume_exists (volname); - -        if (!exists) { -                snprintf (msg, sizeof (msg), "Volume %s does not exist", volname); -                gf_log ("", GF_LOG_ERROR, "%s", msg); -                *op_errstr = gf_strdup (msg); -                ret = -1; -                goto out; -        } else { -                ret = 0; -        } - -        ret  = glusterd_volinfo_find (volname, &volinfo); - -        if (ret) -                goto out; - -        if (!(flags & GF_CLI_FLAG_OP_FORCE)) { -                if (_gf_false == glusterd_is_volume_started (volinfo)) { -                        snprintf (msg, sizeof(msg), "Volume %s " -                                  "is not in the started state", volname); -                        gf_log ("", GF_LOG_ERROR, "Volume %s " -                                "has not been started", volname); -                        *op_errstr = gf_strdup (msg); -                        ret = -1; -                        goto out; -                } -                ret = glusterd_check_gsync_running (volinfo, &is_run); -                if (ret && (is_run == _gf_false)) -                        gf_log ("", GF_LOG_WARNING, "Unable to get the status" -                                 " of active "GEOREP" session"); -                if (is_run) { -                        gf_log ("", GF_LOG_WARNING, GEOREP" sessions active" -                                "for the volume %s ", volname); -                        snprintf (msg, sizeof(msg), GEOREP" sessions are active " -                                  "for the volume '%s'.\nUse 'volume "GEOREP" " -                                  "status' command for more info. Use 'force'" -                                  "option to ignore and stop stop the volume", -                                   volname); -                        *op_errstr = gf_strdup (msg); -                        ret = -1; -                        goto out; -                } - -        } - - -out: - -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - -        return ret; -} - -static int -glusterd_op_stage_delete_volume (dict_t *dict, char **op_errstr) -{ -        int                                     ret = 0; -        char                                    *volname = NULL; -        gf_boolean_t                            exists = _gf_false; -        glusterd_volinfo_t                      *volinfo = NULL; -        char                                    msg[2048] = {0}; - -        ret = dict_get_str (dict, "volname", &volname); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        exists = glusterd_check_volume_exists (volname); - -        if (!exists) { -                snprintf (msg, sizeof (msg), "Volume %s does not exist", -                          volname); -                gf_log ("", GF_LOG_ERROR, "%s", msg); -                *op_errstr = gf_strdup (msg); -                ret = -1; -                goto out; -        } else { -                ret = 0; -        } - -        ret  = glusterd_volinfo_find (volname, &volinfo); - -        if (ret) -                goto out; - -        if (glusterd_is_volume_started (volinfo)) { -                snprintf (msg, sizeof (msg), "Volume %s has been started." -                          "Volume needs to be stopped before deletion.", -                          volname); -                gf_log ("", GF_LOG_ERROR, "%s", msg); -                *op_errstr = gf_strdup (msg); -                ret = -1; -                goto out; -        } - -        ret = 0; - -out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - -        return ret; -} - -static int -glusterd_op_stage_add_brick (dict_t *dict, char **op_errstr) -{ -        int                                     ret = 0; -        char                                    *volname = NULL; -        int                                     count = 0; -        int                                     i = 0; -        char                                    *bricks    = NULL; -        char                                    *brick_list = NULL; -        char                                    *saveptr = NULL; -        char                                    *free_ptr = NULL; -        char                                    *brick = NULL; -        glusterd_brickinfo_t                    *brickinfo = NULL; -        glusterd_volinfo_t                      *volinfo = NULL; -        char                                    cmd_str[1024]; -        glusterd_conf_t                         *priv = NULL; -        char                                    msg[2048] = {0,}; -        gf_boolean_t                            brick_alloc = _gf_false; -        char                                    *all_bricks = NULL; -        char                                    *str_ret = NULL; - -        priv = THIS->private; -        if (!priv) -                goto out; - -        ret = dict_get_str (dict, "volname", &volname); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        ret = glusterd_volinfo_find (volname, &volinfo); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to find volume: %s", volname); -                goto out; -        } - -        if (glusterd_is_defrag_on(volinfo)) { -                snprintf (msg, sizeof(msg), "Volume name %s rebalance is in " -                          "progress. Please retry after completion", volname); -                gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); -                *op_errstr = gf_strdup (msg); -                ret = -1; -                goto out; -        } -        ret = dict_get_int32 (dict, "count", &count); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get count"); -                goto out; -        } - -        ret = dict_get_str (dict, "bricks", &bricks); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); -                goto out; -        } - -        if (bricks) { -                brick_list = gf_strdup (bricks); -                all_bricks = gf_strdup (bricks); -                free_ptr = brick_list; -        } - -        /* Check whether any of the bricks given is the destination brick of the -           replace brick running */ - -        str_ret = glusterd_check_brick_rb_part (all_bricks, count, volinfo); -        if (str_ret) { -                gf_log ("glusterd", GF_LOG_ERROR, -                        "%s", str_ret); -                *op_errstr = gf_strdup (str_ret); -                ret = -1; -                goto out; -        } - -        if (count) -                brick = strtok_r (brick_list+1, " \n", &saveptr); - - -        while ( i < count) { -                if (!glusterd_store_is_valid_brickpath (volname, brick) || -                        !glusterd_is_valid_volfpath (volname, brick)) { -                        snprintf (msg, sizeof (msg), "brick path %s is too " -                                  "long.", brick); -                        gf_log ("", GF_LOG_ERROR, "%s", msg); -                        *op_errstr = gf_strdup (msg); - -                        ret = -1; -                        goto out; - -                } - -                ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, -                                                              &brickinfo); -                if (!ret) { -                        gf_log ("", GF_LOG_ERROR, "Adding duplicate brick: %s", -                                brick); -                        ret = -1; -                        goto out; -                } else { -                        ret = glusterd_brickinfo_from_brick (brick, &brickinfo); -                        if (ret) { -                                gf_log ("", GF_LOG_ERROR, "Add-brick: Unable" -                                        " to get brickinfo"); -                                goto out; -                        } -                        brick_alloc = _gf_true; -                } - -                snprintf (cmd_str, 1024, "%s", brickinfo->path); -                ret = glusterd_resolve_brick (brickinfo); -                if (ret) { -                        gf_log ("glusterd", GF_LOG_ERROR, -                                "resolve brick failed"); -                        goto out; -                } - -                if (!uuid_compare (brickinfo->uuid, priv->uuid)) { -                        ret = glusterd_brick_create_path (brickinfo->hostname, -                                                          brickinfo->path, -                                                          volinfo->volume_id, -                                                          0777, op_errstr); -                        if (ret) -                                goto out; -                } - -                glusterd_brickinfo_delete (brickinfo); -                brick_alloc = _gf_false; -                brickinfo = NULL; -                brick = strtok_r (NULL, " \n", &saveptr); -                i++; -        } - -out: -        if (free_ptr) -                GF_FREE (free_ptr); -        if (brick_alloc && brickinfo) -                glusterd_brickinfo_delete (brickinfo); -        if (str_ret) -                GF_FREE (str_ret); -        if (all_bricks) -                GF_FREE (all_bricks); - -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - -        return ret; -} - -char * -glusterd_check_brick_rb_part (char *bricks, int count, glusterd_volinfo_t *volinfo) -{ -        char                                    *saveptr = NULL; -        char                                    *brick = NULL; -        char                                    *brick_list = NULL; -        int                                     ret = 0; -        glusterd_brickinfo_t                    *brickinfo = NULL; -        uint32_t                                i = 0; -        char                                    *str = NULL; -        char                                    msg[2048] = {0,}; - -        brick_list = gf_strdup (bricks); -        if (!brick_list) { -                gf_log ("glusterd", GF_LOG_ERROR, -                        "Out of memory"); -                ret = -1; -                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; -} - -static int -glusterd_get_rb_dst_brickinfo (glusterd_volinfo_t *volinfo, -                               glusterd_brickinfo_t **brickinfo) -{ -        int32_t                 ret = -1; - -        if (!volinfo || !brickinfo) -                goto out; - -        *brickinfo = volinfo->dst_brick; - -        ret = 0; - -out: -        return ret; -} - -static int -glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, -                                 dict_t *rsp_dict) -{ -        int                                      ret           = 0; -        char                                    *src_brick     = NULL; -        char                                    *dst_brick     = NULL; -        char                                    *volname       = NULL; -        int                                      replace_op    = 0; -        glusterd_volinfo_t                      *volinfo       = NULL; -        glusterd_brickinfo_t                    *src_brickinfo = NULL; -        char                                    *host          = NULL; -        char                                    *path          = NULL; -        char                                    msg[2048]      = {0}; -        char                                    *dup_dstbrick  = NULL; -        glusterd_peerinfo_t                     *peerinfo = NULL; -        glusterd_brickinfo_t                    *dst_brickinfo = NULL; -        gf_boolean_t                            is_run         = _gf_false; - -        ret = dict_get_str (dict, "src-brick", &src_brick); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); -                goto out; -        } - -        gf_log ("", GF_LOG_DEBUG, "src brick=%s", src_brick); - -        ret = dict_get_str (dict, "dst-brick", &dst_brick); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get dest brick"); -                goto out; -        } - -        gf_log ("", GF_LOG_DEBUG, "dst brick=%s", dst_brick); - -        ret = dict_get_str (dict, "volname", &volname); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        ret = dict_get_int32 (dict, "operation", (int32_t *)&replace_op); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "dict get on replace-brick operation failed"); -                goto out; -        } - -        ret = glusterd_volinfo_find (volname, &volinfo); -        if (ret) { -                snprintf (msg, sizeof (msg), "volume: %s does not exist", -                          volname); -                *op_errstr = gf_strdup (msg); -                goto out; -        } - -        if (GLUSTERD_STATUS_STARTED != volinfo->status) { -                ret = -1; -                snprintf (msg, sizeof (msg), "volume: %s is not started", -                          volname); -                *op_errstr = gf_strdup (msg); -                goto out; -        } - -        if (!glusterd_store_is_valid_brickpath (volname, dst_brick) || -                !glusterd_is_valid_volfpath (volname, dst_brick)) { -                snprintf (msg, sizeof (msg), "brick path %s is too " -                          "long.", dst_brick); -                gf_log ("", GF_LOG_ERROR, "%s", msg); -                *op_errstr = gf_strdup (msg); - -                ret = -1; -                goto out; -        } - -        ret = glusterd_check_gsync_running (volinfo, &is_run); -        if (ret && (is_run == _gf_false)) -                gf_log ("", GF_LOG_WARNING, "Unable to get the status" -                                " of active "GEOREP" session"); -        if (is_run) { -                gf_log ("", GF_LOG_WARNING, GEOREP" sessions active" -                        "for the volume %s ", volname); -                snprintf (msg, sizeof(msg), GEOREP" sessions are active " -                                "for the volume %s.\nStop "GEOREP "sessions " -                                "involved in this volume. Use 'volume "GEOREP -                                " status' command for more info.", -                                volname); -                *op_errstr = gf_strdup (msg); -                ret = -1; -                goto out; -        } - -        if (glusterd_is_defrag_on(volinfo)) { -                snprintf (msg, sizeof(msg), "Volume name %s rebalance is in " -                          "progress. Please retry after completion", volname); -                gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); -                *op_errstr = gf_strdup (msg); -                ret = -1; -                goto out; -        } - -        switch (replace_op) { -        case GF_REPLACE_OP_START: -                if (glusterd_is_rb_started (volinfo)) { -                        gf_log ("", GF_LOG_ERROR, "Replace brick is already " -                                "started for volume "); -                        ret = -1; -                        goto out; -                } -                break; -        case GF_REPLACE_OP_PAUSE: -                if (glusterd_is_rb_paused (volinfo)) { -                        gf_log ("", GF_LOG_ERROR, "Replace brick is already " -                                "paused for volume "); -                        ret = -1; -                        goto out; -                } else if (!glusterd_is_rb_started(volinfo)) { -                        gf_log ("", GF_LOG_ERROR, "Replace brick is not" -                                " started for volume "); -                        ret = -1; -                        goto out; -                } -                break; - -        case GF_REPLACE_OP_ABORT: -                if ((!glusterd_is_rb_paused (volinfo)) && -                     (!glusterd_is_rb_started (volinfo))) { -                        gf_log ("", GF_LOG_ERROR, "Replace brick is not" -                                " started or paused for volume "); -                        ret = -1; -                        goto out; -                } -                break; - -        case GF_REPLACE_OP_COMMIT: -                if (!glusterd_is_rb_started (volinfo)) { -                        gf_log ("", GF_LOG_ERROR, "Replace brick is not " -                                "started for volume "); -                        ret = -1; -                        goto out; -                } -                break; - -        case GF_REPLACE_OP_COMMIT_FORCE: break; -        case GF_REPLACE_OP_STATUS: -                break; -        default: -                ret = -1; -                goto out; -        } - -        ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, -                                                      &src_brickinfo); -        if (ret) { -                snprintf (msg, sizeof (msg), "brick: %s does not exist in " -                          "volume: %s", src_brick, volname); -                *op_errstr = gf_strdup (msg); -                goto out; -        } - -        if (!glusterd_is_local_addr (src_brickinfo->hostname)) { -                gf_log ("", GF_LOG_DEBUG, -                        "I AM THE SOURCE HOST"); -                if (src_brickinfo->port && rsp_dict) { -                        ret = dict_set_int32 (rsp_dict, "src-brick-port", -                                              src_brickinfo->port); -                        if (ret) { -                                gf_log ("", GF_LOG_DEBUG, -                                        "Could not set src-brick-port=%d", -                                        src_brickinfo->port); -                        } -                } - -        } - -        dup_dstbrick = gf_strdup (dst_brick); -        if (!dup_dstbrick) { -                ret = -1; -                gf_log ("", GF_LOG_ERROR, "Memory allocation failed"); -                goto out; -        } -        host = strtok (dup_dstbrick, ":"); -        path = strtok (NULL, ":"); - -        if (!host || !path) { -                gf_log ("", GF_LOG_ERROR, -                        "dst brick %s is not of form <HOSTNAME>:<export-dir>", -                        dst_brick); -                ret = -1; -                goto out; -        } -        if (!glusterd_brickinfo_get (NULL, host, path, NULL)) { -                snprintf(msg, sizeof(msg), "Brick: %s:%s already in use", -                         host, path); -                *op_errstr = gf_strdup (msg); -                ret = -1; -                goto out; -        } - -        if ((volinfo->rb_status ==GF_RB_STATUS_NONE) && -            (replace_op == GF_REPLACE_OP_START)) { -                ret = glusterd_brickinfo_from_brick (dst_brick, &dst_brickinfo); -                volinfo->src_brick = src_brickinfo; -                volinfo->dst_brick = dst_brickinfo; -        } else { -                ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); -        } - -        if (glusterd_rb_check_bricks (volinfo, src_brickinfo, dst_brickinfo)) { -                gf_log ("", GF_LOG_ERROR, "replace brick: incorrect source or" -                       "  destination bricks specified"); -                ret = -1; -                goto out; -       } -        if (!glusterd_is_local_addr (host)) { -                ret = glusterd_brick_create_path (host, path, -                                                  volinfo->volume_id, 0777, -                                                  op_errstr); -                if (ret) -                        goto out; -        } else { -                ret = glusterd_friend_find (NULL, host, &peerinfo); -                if (ret) { -                        snprintf (msg, sizeof (msg), "%s, is not a friend", -                                  host); -                        *op_errstr = gf_strdup (msg); -                        goto out; -                } - -                if (!peerinfo->connected) { -                        snprintf (msg, sizeof (msg), "%s, is not connected at " -                                  "the moment", host); -                        *op_errstr = gf_strdup (msg); -                        ret = -1; -                        goto out; -                } - -                if (GD_FRIEND_STATE_BEFRIENDED != peerinfo->state.state) { -                        snprintf (msg, sizeof (msg), "%s, is not befriended " -                                  "at the moment", host); -                        *op_errstr = gf_strdup (msg); -                        ret = -1; -                        goto out; -                } -        } -        ret = 0; - -out: -        if (dup_dstbrick) -                GF_FREE (dup_dstbrick); -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - -        return ret; -} - -static int -glusterd_op_stage_log_level (dict_t *dict, char **op_errstr) -{ -        int                 ret            = -1; -        gf_boolean_t        exists         = _gf_false; -        dict_t             *val_dict       = NULL; -        char               *volname        = NULL; -        char               *xlator         = NULL; -        char               *loglevel       = NULL; -        glusterd_volinfo_t *volinfo        = NULL; -        glusterd_conf_t    *priv           = NULL; -        xlator_t           *this           = NULL; -        char msg[2048]                     = {0,}; - -        GF_ASSERT (dict); -        this = THIS; -        GF_ASSERT (this); -        priv = this->private; -        GF_ASSERT(priv); - -        val_dict = dict_new (); -        if (!val_dict) -                goto out; - -        ret = dict_get_str (dict, "volname", &volname); -        if (ret) { -                gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        /* -         * check for existence of the gieven volume -         */ -        exists = glusterd_check_volume_exists (volname); -        ret = glusterd_volinfo_find (volname, &volinfo); -        if (!exists || ret) { -                snprintf (msg, sizeof(msg), "Volume %s does not exist", volname); -                gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - -                *op_errstr = gf_strdup(msg); -                ret = -1; -                goto out; -        } - -        ret = dict_get_str (dict, "xlator", &xlator); -        if (ret) { -                gf_log ("glusterd", GF_LOG_ERROR, "Unable to get translator name"); -                goto out; -        } - -        ret = dict_get_str (dict, "loglevel", &loglevel); -        if (ret) { -                gf_log ("glusterd", GF_LOG_ERROR, "Unable to get loglevel"); -                goto out; -        } - -        ret = 0; - - out: -        if (val_dict) -                dict_unref (val_dict); - -        if (ret) { -                if (!(*op_errstr)) { -                        *op_errstr = gf_strdup ("Error, Validation Failed"); -                        gf_log ("glusterd", GF_LOG_DEBUG, "Error, Cannot Validate option: %s", -                                *op_errstr); -                } -        } - -        gf_log ("glusterd", GF_LOG_DEBUG, "Returning: %d", ret); -        return ret; -} - -static int -glusterd_op_stage_log_filename (dict_t *dict, char **op_errstr) -{ -        int                                     ret = -1; -        char                                    *volname = NULL; -        gf_boolean_t                            exists = _gf_false; -        char                                    msg[2048] = {0}; -        char                                    *path = NULL; -        char                                    hostname[2048] = {0}; -        char                                    *brick = NULL; -        glusterd_volinfo_t                      *volinfo = NULL; - -        ret = dict_get_str (dict, "volname", &volname); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        exists = glusterd_check_volume_exists (volname); -        ret = glusterd_volinfo_find (volname, &volinfo); -        if (!exists || ret) { -                snprintf (msg, sizeof (msg), "Volume %s does not exist", -                          volname); -                gf_log ("", GF_LOG_ERROR, "%s", msg); -                *op_errstr = gf_strdup (msg); -                ret = -1; -                goto out; -        } - -        ret = dict_get_str (dict, "brick", &brick); -        if (ret) -                goto out; - -        if (strchr (brick, ':')) { -                ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, -                                                              NULL); -                if (ret) { -                        snprintf (msg, sizeof (msg), "Incorrect brick %s " -                                  "for volume %s", brick, volname); -                        gf_log ("", GF_LOG_ERROR, "%s", msg); -                        *op_errstr = gf_strdup (msg); -                        goto out; -                } -        } - -        ret = dict_get_str (dict, "path", &path); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "path not found"); -                goto out; -        } - -        ret = gethostname (hostname, sizeof (hostname)); -        if (ret) { -                snprintf (msg, sizeof (msg), "Failed to get hostname, error:%s", -                strerror (errno)); -                gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); -                *op_errstr = gf_strdup (msg); -                goto out; -        } - -        ret = glusterd_brick_create_path (hostname, path, volinfo->volume_id, -                                          0777, op_errstr); -        if (ret) -                goto out; -out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - -        return ret; -} - -static int -glusterd_op_stage_log_rotate (dict_t *dict, char **op_errstr) -{ -        int                                     ret = -1; -        char                                    *volname = NULL; -        glusterd_volinfo_t                      *volinfo = NULL; -        gf_boolean_t                            exists = _gf_false; -        char                                    msg[2048] = {0}; -        char                                    *brick = NULL; - -        ret = dict_get_str (dict, "volname", &volname); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        exists = glusterd_check_volume_exists (volname); -        ret = glusterd_volinfo_find (volname, &volinfo); -        if (!exists) { -                snprintf (msg, sizeof (msg), "Volume %s does not exist", -                          volname); -                gf_log ("", GF_LOG_ERROR, "%s", msg); -                *op_errstr = gf_strdup (msg); -                ret = -1; -                goto out; -        } - -        if (_gf_false == glusterd_is_volume_started (volinfo)) { -                snprintf (msg, sizeof (msg), "Volume %s needs to be started before" -                          " log rotate.", volname); -                gf_log ("", GF_LOG_ERROR, "%s", msg); -                *op_errstr = gf_strdup (msg); -                ret = -1; -                goto out; -        } - -        ret = dict_get_str (dict, "brick", &brick); -        if (ret) -                goto out; - -        if (strchr (brick, ':')) { -                ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, -                                                              NULL); -                if (ret) { -                        snprintf (msg, sizeof (msg), "Incorrect brick %s " -                                  "for volume %s", brick, volname); -                        gf_log ("", GF_LOG_ERROR, "%s", msg); -                        *op_errstr = gf_strdup (msg); -                        goto out; -                } -        } -out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - -        return ret; -}  static int  glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr) @@ -1540,264 +489,6 @@ out:  } -static int -glusterd_op_perform_remove_brick (glusterd_volinfo_t  *volinfo, char *brick) -{ - -        glusterd_brickinfo_t    *brickinfo = NULL; -        char                    *dup_brick = NULL; -        glusterd_conf_t         *priv = NULL; -        int32_t                 ret = -1; - -        GF_ASSERT (volinfo); -        GF_ASSERT (brick); - -        priv = THIS->private; - -        dup_brick = gf_strdup (brick); -        if (!dup_brick) -                goto out; - -        ret = glusterd_volume_brickinfo_get_by_brick (dup_brick, volinfo,  &brickinfo); -        if (ret) -                goto out; - -        ret = glusterd_resolve_brick (brickinfo); -        if (ret) -                goto out; - -        if (GLUSTERD_STATUS_STARTED == volinfo->status) { -                ret = glusterd_brick_stop (volinfo, brickinfo); -                if (ret) { -                        gf_log ("", GF_LOG_ERROR, "Unable to stop " -                                "glusterfs, ret: %d", ret); -                        goto out; -                } -        } -        glusterd_delete_brick (volinfo, brickinfo); -out: -        if (dup_brick) -                GF_FREE (dup_brick); - -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; -} - -static int -glusterd_op_perform_replace_brick (glusterd_volinfo_t  *volinfo, -                                   char *old_brick, char  *new_brick) -{ -        glusterd_brickinfo_t                    *old_brickinfo = NULL; -        glusterd_brickinfo_t                    *new_brickinfo = NULL; -        int32_t                                 ret = -1; -        glusterd_conf_t                         *priv = NULL; - -        priv = THIS->private; - -        GF_ASSERT (volinfo); - -        ret = glusterd_brickinfo_from_brick (new_brick, -                                             &new_brickinfo); -        if (ret) -                goto out; - -        ret = glusterd_volume_brickinfo_get_by_brick (old_brick, volinfo, -                                                      &old_brickinfo); -        if (ret) -                goto out; - -        ret = glusterd_resolve_brick (new_brickinfo); -        if (ret) -                goto out; - -        list_add_tail (&new_brickinfo->brick_list, -                       &old_brickinfo->brick_list); - -        volinfo->brick_count++; - -        ret = glusterd_op_perform_remove_brick (volinfo, old_brick); -        if (ret) -                goto out; - -        ret = glusterd_create_volfiles_and_notify_services (volinfo); -        if (ret) -                goto out; - -        if (GLUSTERD_STATUS_STARTED == volinfo->status) { -                ret = glusterd_brick_start (volinfo, new_brickinfo); -                if (ret) -                        goto out; -        } - - -out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; -} - -static int -glusterd_op_perform_add_bricks (glusterd_volinfo_t  *volinfo, int32_t count, -                                char  *bricks) -{ -        glusterd_brickinfo_t                    *brickinfo = NULL; -        char                                    *brick = NULL; -        int32_t                                 i = 1; -        char                                    *brick_list = NULL; -        char                                    *free_ptr1  = NULL; -        char                                    *free_ptr2  = NULL; -        char                                    *saveptr = NULL; -        int32_t                                 ret = -1; -        glusterd_conf_t                         *priv = NULL; - -        priv = THIS->private; - -        GF_ASSERT (volinfo); - -        if (bricks) { -                brick_list = gf_strdup (bricks); -                free_ptr1 = brick_list; -        } - -        if (count) -                brick = strtok_r (brick_list+1, " \n", &saveptr); - -        while ( i <= count) { -                ret = glusterd_brickinfo_from_brick (brick, &brickinfo); -                if (ret) -                        goto out; - -                ret = glusterd_resolve_brick (brickinfo); -                if (ret) -                        goto out; -                list_add_tail (&brickinfo->brick_list, &volinfo->bricks); -                brick = strtok_r (NULL, " \n", &saveptr); -                i++; -                volinfo->brick_count++; - -        } - -        brick_list = gf_strdup (bricks); -        free_ptr2 = brick_list; -        i = 1; - -        if (count) -                brick = strtok_r (brick_list+1, " \n", &saveptr); - -        ret = glusterd_create_volfiles_and_notify_services (volinfo); -        if (ret) -                goto out; - -        while (i <= count) { - -                ret = glusterd_volume_brickinfo_get_by_brick (brick, volinfo, -                                                              &brickinfo); -                if (ret) -                        goto out; - -                if (GLUSTERD_STATUS_STARTED == volinfo->status) { -                        ret = glusterd_brick_start (volinfo, brickinfo); -                        if (ret) -                                goto out; -                } -                i++; -                brick = strtok_r (NULL, " \n", &saveptr); -        } - -out: -        if (free_ptr1) -                GF_FREE (free_ptr1); -        if (free_ptr2) -                GF_FREE (free_ptr2); - -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; -} - - -static int -glusterd_op_stage_remove_brick (dict_t *dict) -{ -        int                                     ret = -1; -        char                                    *volname = NULL; -        glusterd_volinfo_t                      *volinfo = NULL; -        dict_t                                  *ctx     = NULL; -        char                                    *errstr  = NULL; -        int32_t                                 brick_count = 0; - -        ret = dict_get_str (dict, "volname", &volname); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        ret = glusterd_volinfo_find (volname, &volinfo); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Volume %s does not exist", volname); -                goto out; -        } - -        if (glusterd_is_defrag_on(volinfo)) { -                ctx = glusterd_op_get_ctx (); -                errstr = gf_strdup("Rebalance is in progress. Please retry" -                                    " after completion"); -                if (!errstr) { -                        ret = -1; -                        goto out; -                } -                gf_log ("glusterd", GF_LOG_ERROR, "%s", errstr); -                ret = dict_set_dynstr (ctx, "errstr", errstr); -                if (ret) { -                        GF_FREE (errstr); -                        gf_log ("", GF_LOG_DEBUG, -                                "failed to set errstr ctx"); -                        goto out; -                } - -                ret = -1; -                goto out; -        } - -        ret = dict_get_int32 (dict, "count", &brick_count); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get brick count"); -                goto out; -        } - -        if (volinfo->brick_count == brick_count) { -                ctx = glusterd_op_get_ctx (); -                if (!ctx) { -                        gf_log ("", GF_LOG_ERROR, -                                "Operation Context is not present"); -                        ret = -1; -                        goto out; -                } -                errstr = gf_strdup ("Deleting all the bricks of the " -                                    "volume is not allowed"); -                if (!errstr) { -                        gf_log ("", GF_LOG_ERROR, "Out of memory"); -                        ret = -1; -                        goto out; -                } - -                ret = dict_set_dynstr (ctx, "errstr", errstr); -                if (ret) { -                        GF_FREE (errstr); -                        gf_log ("", GF_LOG_DEBUG, -                                "failed to set pump status in ctx"); -                        goto out; -                } - -                ret = -1; -                goto out; -        } - -out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - -        return ret; -}  static int  glusterd_op_stage_sync_volume (dict_t *dict, char **op_errstr) @@ -1901,841 +592,6 @@ glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr)          return ret;  } -/***** - * - * glusterd_urltransform* internal API - * - *****/ - -static void -glusterd_urltransform_init (runner_t *runner, const char *transname) -{ -        runinit (runner); -        runner_add_arg (runner, GSYNCD_PREFIX"/gsyncd"); -        runner_argprintf (runner, "--%s-url", transname); -} - -static void -glusterd_urltransform_add (runner_t *runner, const char *url) -{ -        runner_add_arg (runner, url); -} - -static void -_glusterd_urltransform_add_iter (dict_t *dict, char *key, data_t *value, void *data) -{ -        runner_t *runner = (runner_t *)data; -        char *slave = NULL; - -        slave = strchr (value->data, ':'); -        GF_ASSERT (slave); -        slave++; -        runner_add_arg (runner, slave); -} - -static void -glusterd_urltransform_free (char **linearr, unsigned n) -{ -        int i = 0; - -        for (; i < n; i++) -                GF_FREE (linearr[i]); - -        GF_FREE (linearr); -} - -static int -glusterd_urltransform (runner_t *runner, char ***linearrp) -{ -        char **linearr = NULL; -        char *line = NULL; -        unsigned arr_len = 32; -        unsigned arr_idx = 0; -        gf_boolean_t error = _gf_false; - -        linearr = GF_CALLOC (arr_len, sizeof (char *), gf_gld_mt_linearr); -        if (!linearr) { -                error = _gf_true; -                goto out; -        } - -        runner_redir (runner, STDOUT_FILENO, RUN_PIPE); -        if (runner_start (runner) != 0) { -                gf_log ("", GF_LOG_ERROR, "spawning child failed"); - -                error = _gf_true; -                goto out; -        } - -        arr_idx = 0; -        for (;;) { -                line = GF_MALLOC (1024, gf_gld_mt_linebuf); -                if (!line) { -                        error = _gf_true; -                        goto out; -                } - -                if (fgets (line, 1024, runner_chio (runner, STDOUT_FILENO)) == -                    NULL) -                        break; - -                if (line[strlen (line) - 1] != '\n') { -                        GF_FREE (line); -                        error = _gf_true; -                        goto out; -                } -                line[strlen (line) - 1] = '\0'; - -                if (arr_idx == arr_len) { -                        arr_len <<= 1; -                        linearr = GF_REALLOC (linearr, arr_len); -                        if (!linearr) { -                                GF_FREE (line); -                                error = _gf_true; -                                goto out; -                        } -                } -                linearr[arr_idx] = line; - -                arr_idx++; -        } - - out: - -        /* XXX chpid field is not exported by run API -         * but runner_end() does not abort the invoked -         * process (ie. it might block in waitpid(2)) -         * so we resort to a manual kill a the private field -         */ -        if (error && runner->chpid > 0) -                kill (runner->chpid, SIGKILL); - -        if (runner_end (runner) != 0) -                error = _gf_true; - -        if (error) { -                gf_log ("", GF_LOG_ERROR, "reading data from child failed"); -                glusterd_urltransform_free (linearr, arr_idx); -                return -1; -        } - -        *linearrp = linearr; -        return arr_idx; -} - -static int -glusterd_urltransform_single (const char *url, const char *transname, -                              char ***linearrp) -{ -        runner_t runner = {0,}; - -        glusterd_urltransform_init (&runner, transname); -        glusterd_urltransform_add (&runner, url); -        return glusterd_urltransform (&runner, linearrp); -} - - -struct dictidxmark { -        unsigned isrch; -        unsigned ithis; -        char *ikey; -}; - -static void -_dict_mark_atindex (dict_t *dict, char *key, data_t *value, void *data) -{ -        struct dictidxmark *dim = data; - -        if (dim->isrch == dim->ithis) -                dim->ikey = key; - -        dim->ithis++; -} - -static char * -dict_get_by_index (dict_t *dict, unsigned i) -{ -        struct dictidxmark dim = {0,}; - -        dim.isrch = i; -        dict_foreach (dict, _dict_mark_atindex, &dim); - -        return dim.ikey; -} - -static int -glusterd_get_slave (glusterd_volinfo_t *vol, const char *slaveurl, char **slavekey) -{ -        runner_t runner = {0,}; -        int n = 0; -        int i = 0; -        char **linearr = NULL; - -        glusterd_urltransform_init (&runner, "canonicalize"); -        dict_foreach (vol->gsync_slaves, _glusterd_urltransform_add_iter, &runner); -        glusterd_urltransform_add (&runner, slaveurl); - -        n = glusterd_urltransform (&runner, &linearr); -        if (n == -1) -                return -2; - -        for (i = 0; i < n - 1; i++) { -                if (strcmp (linearr[i], linearr[n - 1]) == 0) -                        break; -        } -        glusterd_urltransform_free (linearr, i); - -        if (i < n - 1) -                *slavekey = dict_get_by_index (vol->gsync_slaves, i); -        else -                i = -1; - -        return i; -} - - -static int -glusterd_query_extutil (char *resbuf, runner_t *runner) -{ -        char               *ptr = NULL; -        int                 ret = 0; - -        runner_redir (runner, STDOUT_FILENO, RUN_PIPE); -        if (runner_start (runner) != 0) { -                gf_log ("", GF_LOG_ERROR, "spawning child failed"); - -                return -1; -        } - -        ptr = fgets(resbuf, PATH_MAX, runner_chio (runner, STDOUT_FILENO)); -        if (ptr) -                resbuf[strlen(resbuf)-1] = '\0'; //strip off \n - -        ret = runner_end (runner); -        if (ret) -                gf_log ("", GF_LOG_ERROR, "reading data from child failed"); - -        return ret ? -1 : 0; -} - -int -glusterd_gsync_get_param_file (char *prmfile, const char *param, char *master, -                               char *slave, char *gl_workdir) -{ -        runner_t            runner = {0,}; - -        runinit (&runner); -        runner_add_args  (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); -        runner_argprintf (&runner, "%s/"GSYNC_CONF, gl_workdir); -        runner_argprintf (&runner, ":%s", master); -        runner_add_args  (&runner, slave, "--config-get", NULL); -        runner_argprintf (&runner, "%s-file", param); - -        return glusterd_query_extutil (prmfile, &runner); -} - -static int -gsyncd_getpidfile (char *master, char *slave, char *pidfile) -{ -        int                ret             = -1; -        glusterd_conf_t    *priv  = NULL; - -        GF_ASSERT (THIS); -        GF_ASSERT (THIS->private); - -        priv = THIS->private; - -        GF_VALIDATE_OR_GOTO ("gsync", master, out); -        GF_VALIDATE_OR_GOTO ("gsync", slave, out); - -        ret = glusterd_gsync_get_param_file (pidfile, "pid", master, -                                              slave, priv->workdir); -        if (ret == -1) { -                ret = -2; -                gf_log ("", GF_LOG_WARNING, "failed to create the pidfile string"); -                goto out; -        } - -        ret = open (pidfile, O_RDWR); - - out: -        return ret; -} - -static int -gsync_status_byfd (int fd) -{ -        GF_ASSERT (fd >= -1); - -        if (lockf (fd, F_TEST, 0) == -1 && -            (errno == EAGAIN || errno == EACCES)) -                /* gsyncd keeps the pidfile locked */ -                return 0; - -        return -1; -} - -/* status: return 0 when gsync is running - * return -1 when not running - */ -int -gsync_status (char *master, char *slave, int *status) -{ -        char pidfile[PATH_MAX] = {0,}; -        int  fd                = -1; - -        fd = gsyncd_getpidfile (master, slave, pidfile); -        if (fd == -2) -                return -1; - -        *status = gsync_status_byfd (fd); - -        close (fd); -        return 0; -} - - -int32_t -glusterd_gsync_volinfo_dict_set (glusterd_volinfo_t *volinfo, -                                 char *key, char *value) -{ -        int32_t  ret            = -1; -        char    *gsync_status   = NULL; - -        gsync_status = gf_strdup (value); -        if (!gsync_status) { -                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); -                goto out; -        } - -        ret = dict_set_dynstr (volinfo->dict, key, gsync_status); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to set dict"); -                goto out; -        } - -        ret = 0; -out: -        return 0; -} - -int -gsync_verify_config_options (dict_t *dict, char **op_errstr) -{ -        char  **resopt    = NULL; -        int     i         = 0; -        char   *subop     = NULL; -        char   *slave     = NULL; -        char   *op_name   = NULL; -        char   *op_value  = NULL; -        gf_boolean_t banned = _gf_true; - -        if (dict_get_str (dict, "subop", &subop) != 0) { -                gf_log ("", GF_LOG_WARNING, "missing subop"); -                *op_errstr = gf_strdup ("Invalid config request"); -                return -1; -        } - -        if (dict_get_str (dict, "slave", &slave) != 0) { -                gf_log ("", GF_LOG_WARNING, GEOREP" CONFIG: no slave given"); -                *op_errstr = gf_strdup ("Slave required"); -                return -1; -        } - -        if (strcmp (subop, "get-all") == 0) -                return 0; - -        if (dict_get_str (dict, "op_name", &op_name) != 0) { -                gf_log ("", GF_LOG_WARNING, "option name missing"); -                *op_errstr = gf_strdup ("Option name missing"); -                return -1; -        } - -        if (runcmd (GSYNCD_PREFIX"/gsyncd", "--config-check", op_name, NULL)) { -                gf_log ("", GF_LOG_WARNING, "Invalid option %s", op_name); -                *op_errstr = gf_strdup ("Invalid option"); - -                return -1; -        } - -        if (strcmp (subop, "get") == 0) -                return 0; - -        if (strcmp (subop, "set") != 0 && strcmp (subop, "del") != 0) { -                gf_log ("", GF_LOG_WARNING, "unknown subop %s", subop); -                *op_errstr = gf_strdup ("Invalid config request"); -                return -1; -        } - -        if (strcmp (subop, "set") == 0 && -            dict_get_str (dict, "op_value", &op_value) != 0) { -                gf_log ("", GF_LOG_WARNING, "missing value for set"); -                *op_errstr = gf_strdup ("missing value"); -        } - -        /* match option name against reserved options, modulo -/_ -         * difference -         */ -        for (resopt = gsync_reserved_opts; *resopt; resopt++) { -                banned = _gf_true; -                for (i = 0; (*resopt)[i] && op_name[i]; i++) { -                        if ((*resopt)[i] == op_name[i] || -                            ((*resopt)[i] == '-' && op_name[i] == '_')) -                                continue; -                        banned = _gf_false; -                } -                if (banned) { -                        gf_log ("", GF_LOG_WARNING, "Reserved option %s", op_name); -                        *op_errstr = gf_strdup ("Reserved option"); - -                        return -1; -                        break; -                } -        } - -        return 0; -} - -static void -_get_status_mst_slv (dict_t *this, char *key, data_t *value, void *data) -{ -        glusterd_gsync_status_temp_t  *param = NULL; -        char                          *slave = NULL; -        int                           ret = 0; - -        param = (glusterd_gsync_status_temp_t *)data; - -        GF_ASSERT (param); -        GF_ASSERT (param->volinfo); - -        slave = strchr(value->data, ':'); -        if (slave) -                slave ++; -        else -                return; - -        ret = glusterd_get_gsync_status_mst_slv(param->volinfo, -                                                slave, param->rsp_dict); - -} - -static void -_get_max_gsync_slave_num (dict_t *this, char *key, data_t *value, void *data) -{ -        int  tmp_slvnum = 0; -        int *slvnum = (int *)data; - -        sscanf (key, "slave%d", &tmp_slvnum); -        if (tmp_slvnum > *slvnum) -                *slvnum = tmp_slvnum; -} - -static int -glusterd_remove_slave_in_info (glusterd_volinfo_t *volinfo, char *slave, -                               char **op_errstr) -{ -        int   ret = 0; -        char *slavekey = NULL; - -        GF_ASSERT (volinfo); -        GF_ASSERT (slave); - -        ret = glusterd_get_slave (volinfo, slave, &slavekey); -        if (ret < 0) { -                ret++; -                goto out; -        } - -        dict_del (volinfo->gsync_slaves, slavekey); - -        ret = glusterd_store_volinfo (volinfo, -                                      GLUSTERD_VOLINFO_VER_AC_INCREMENT); -        if (ret) { -                 *op_errstr = gf_strdup ("Failed to store the Volume" -                                         "information"); -                goto out; -        } - out: -        gf_log ("", GF_LOG_DEBUG, "returning %d", ret); -        return ret; - -} - -static int -glusterd_gsync_get_uuid (char *slave, glusterd_volinfo_t *vol, -                         uuid_t uuid) -{ -        int   ret = 0; -        char *slavekey = NULL; -        char *slaveentry = NULL; -        char *t = NULL; - -        GF_ASSERT (vol); -        GF_ASSERT (slave); - -        ret = glusterd_get_slave (vol, slave, &slavekey); -        if (ret < 0) { -                /* XXX colliding cases of failure and non-extant -                 * slave... now just doing this as callers of this -                 * function can make sense only of -1 and 0 as retvals; -                 * getting at the proper semanticals will involve -                 * fixing callers as well. -                 */ -                ret = -1; -                goto out; -        } - -        ret = dict_get_str (vol->gsync_slaves, slavekey, &slaveentry); -        GF_ASSERT (ret == 0); - -        t = strchr (slaveentry, ':'); -        GF_ASSERT (t); -        *t = '\0'; -        ret = uuid_parse (slaveentry, uuid); -        *t = ':'; - - out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; -} - -static int -glusterd_check_gsync_running_local (char *master, char *slave, -                                    gf_boolean_t *is_run) -{ -        int                 ret    = -1; -        int                 ret_status = 0; - -        GF_ASSERT (master); -        GF_ASSERT (slave); -        GF_ASSERT (is_run); - -        *is_run = _gf_false; -        ret = gsync_status (master, slave, &ret_status); -        if (ret == 0 && ret_status == 0) { -                *is_run = _gf_true; -        } else if (ret == -1) { -                gf_log ("", GF_LOG_WARNING, GEOREP" validation " -                        " failed"); -                goto out; -        } -        ret = 0; - out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; - -} - -static int -glusterd_store_slave_in_info (glusterd_volinfo_t *volinfo, char *slave, -                              char *host_uuid, char **op_errstr) -{ -        int    ret = 0; -        int    maxslv = 0; -        char **linearr = NULL; -        char  *value = NULL; -        char  *slavekey = NULL; -        char  *slaveentry = NULL; -        char   key[512] = {0, }; -        char  *t = NULL; - -        GF_ASSERT (volinfo); -        GF_ASSERT (slave); -        GF_ASSERT (host_uuid); - -        ret = glusterd_get_slave (volinfo, slave, &slavekey); -        switch (ret) { -        case -2: -                ret = -1; -                goto out; -        case -1: -                break; -        default: -                GF_ASSERT (ret > 0); -                ret = dict_get_str (volinfo->gsync_slaves, slavekey, &slaveentry); -                GF_ASSERT (ret == 0); - -                /* same-name + same-uuid slave entries should have been filtered -                 * out in glusterd_op_verify_gsync_start_options(), so we can -                 * assert an uuid mismatch -                 */ -                t = strtail (slaveentry, host_uuid); -                GF_ASSERT (!t || *t != ':') - -                gf_log ("", GF_LOG_ERROR, GEOREP" has already been invoked for " -                                          "the %s (master) and %s (slave) " -                                          "from a different machine", -                                           volinfo->volname, slave); -                *op_errstr = gf_strdup (GEOREP" already running on an " -                                        "another machine"); -                ret = -1; -                goto out; -        } - -        ret = glusterd_urltransform_single (slave, "normalize", &linearr); -        if (ret == -1) -                goto out; -        ret = gf_asprintf (&value,  "%s:%s", host_uuid, linearr[0]); -        glusterd_urltransform_free (linearr, 1); -        if (ret  == -1) -                goto out; - -        dict_foreach (volinfo->gsync_slaves, _get_max_gsync_slave_num, &maxslv); -        snprintf (key, 512, "slave%d", maxslv + 1); -        ret = dict_set_dynstr (volinfo->gsync_slaves, key, value); -        if (ret) -                goto out; - -        ret = glusterd_store_volinfo (volinfo, -                                      GLUSTERD_VOLINFO_VER_AC_INCREMENT); -        if (ret) { -                *op_errstr = gf_strdup ("Failed to store the Volume " -                                        "information"); -                goto out; -        } -        ret = 0; - out: -        return ret; -} - - -static int -glusterd_op_verify_gsync_start_options (glusterd_volinfo_t *volinfo, -                                        char *slave, char **op_errstr) -{ -        int                     ret = -1; -        gf_boolean_t            is_running = _gf_false; -        char                    msg[2048] = {0}; -        uuid_t                  uuid = {0}; -        glusterd_conf_t         *priv = NULL; -        xlator_t                *this = NULL; - -        this = THIS; - -        GF_ASSERT (volinfo); -        GF_ASSERT (slave); -        GF_ASSERT (op_errstr); -        GF_ASSERT (this && this->private); - -        priv  = this->private; - -        if (GLUSTERD_STATUS_STARTED != volinfo->status) { -                snprintf (msg, sizeof (msg), "Volume %s needs to be started " -                          "before "GEOREP" start", volinfo->volname); -                goto out; -        } -        /*Check if the gsync is already started in cmd. inited host -         * If so initiate add it into the glusterd's priv*/ -        ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); -        if ((ret == 0) && (uuid_compare (priv->uuid, uuid) == 0)) { -                ret = glusterd_check_gsync_running_local (volinfo->volname, -                                                          slave, &is_running); -                if (ret) { -                        snprintf (msg, sizeof (msg), GEOREP" start option " -                                  "validation failed "); -                        goto out; -                } -                if (_gf_true == is_running) { -                        snprintf (msg, sizeof (msg), GEOREP " session between" -                                  " %s & %s already started", volinfo->volname, -                                  slave); -                        ret = -1; -                        goto out; -                } -        } -        ret = 0; -out: -        if (ret && (msg[0] != '\0')) { -                *op_errstr = gf_strdup (msg); -        } -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; -} - -int -glusterd_check_gsync_running (glusterd_volinfo_t *volinfo, gf_boolean_t *flag) -{ - -        GF_ASSERT (volinfo); -        GF_ASSERT (flag); - -        if (volinfo->gsync_slaves->count) -                *flag = _gf_true; -        else -                *flag = _gf_false; - -        return 0; -} - -static int -glusterd_op_verify_gsync_running (glusterd_volinfo_t *volinfo, -                                  char *slave, char **op_errstr) -{ -        int                     ret = -1; -        char                    msg[2048] = {0}; -        uuid_t                  uuid = {0}; -        glusterd_conf_t         *priv = NULL; - -        GF_ASSERT (THIS && THIS->private); -        GF_ASSERT (volinfo); -        GF_ASSERT (slave); -        GF_ASSERT (op_errstr); - -        priv = THIS->private; - -        if (GLUSTERD_STATUS_STARTED != volinfo->status) { -                snprintf (msg, sizeof (msg), "Volume %s needs to be started " -                          "before "GEOREP" start", volinfo->volname); - -                goto out; -        } -        ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); -        if (ret == -1) { -                snprintf (msg, sizeof (msg), GEOREP" session between %s & %s" -                          " not active", volinfo->volname, slave); -                goto out; -        } - -        ret = 0; -out: -        if (ret && (msg[0] != '\0')) { -                *op_errstr = gf_strdup (msg); -        } -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; -} - -static int -glusterd_verify_gsync_status_opts (dict_t *dict, char **op_errstr) -{ -        char               *slave  = NULL; -        char               *volname = NULL; -        char               errmsg[PATH_MAX] = {0, }; -        gf_boolean_t       exists = _gf_false; -        glusterd_volinfo_t *volinfo = NULL; -        int                ret = 0; - -        ret = dict_get_str (dict, "master", &volname); -        if (ret < 0) { -                ret = 0; -                goto out; -        } - -        exists = glusterd_check_volume_exists (volname); -        ret = glusterd_volinfo_find (volname, &volinfo); -        if ((ret) || (!exists)) { -                gf_log ("", GF_LOG_WARNING, "volume name does not exist"); -                snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" -                          " exist", volname); -                *op_errstr = gf_strdup (errmsg); -                ret = -1; -                goto out; -        } - -        ret = dict_get_str (dict, "slave", &slave); -        if (ret < 0) { -                ret = 0; -                goto out; -        } - - out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; - -} - - -static int -glusterd_op_gsync_args_get (dict_t *dict, char **op_errstr, -                            char **master, char **slave) -{ - -        int             ret = -1; -        GF_ASSERT (dict); -        GF_ASSERT (op_errstr); -        GF_ASSERT (master); -        GF_ASSERT (slave); - -        ret = dict_get_str (dict, "master", master); -        if (ret < 0) { -                gf_log ("", GF_LOG_WARNING, "master not found"); -                *op_errstr = gf_strdup ("master not found"); -                goto out; -        } - -        ret = dict_get_str (dict, "slave", slave); -        if (ret < 0) { -                gf_log ("", GF_LOG_WARNING, "slave not found"); -                *op_errstr = gf_strdup ("slave not found"); -                goto out; -        } - - -        ret = 0; -out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; -} - -static int -glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr) -{ -        int                     ret     = 0; -        int                     type    = 0; -        char                    *volname = NULL; -        char                    *slave   = NULL; -        gf_boolean_t            exists   = _gf_false; -        glusterd_volinfo_t      *volinfo = NULL; -        char                    errmsg[PATH_MAX] = {0,}; - - -        ret = dict_get_int32 (dict, "type", &type); -        if (ret < 0) { -                gf_log ("", GF_LOG_WARNING, "command type not found"); -                *op_errstr = gf_strdup ("command unsuccessful"); -                goto out; -        } - -        switch (type) { -        case GF_GSYNC_OPTION_TYPE_STATUS: -                ret = glusterd_verify_gsync_status_opts (dict, op_errstr); - -                goto out; -        case GF_GSYNC_OPTION_TYPE_CONFIG: -                ret = gsync_verify_config_options (dict, op_errstr); - -                goto out; -        } - -        ret = glusterd_op_gsync_args_get (dict, op_errstr, &volname, &slave); -        if (ret) -                goto out; - -        exists = glusterd_check_volume_exists (volname); -        ret = glusterd_volinfo_find (volname, &volinfo); -        if ((ret) || (!exists)) { -                gf_log ("", GF_LOG_WARNING, "volume name does not exist"); -                snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" -                          " exist", volname); -                *op_errstr = gf_strdup (errmsg); -                ret = -1; -                goto out; -        } - -        switch (type) { -        case GF_GSYNC_OPTION_TYPE_START: -                ret = glusterd_op_verify_gsync_start_options (volinfo, slave, -                                                              op_errstr); -                break; -        case GF_GSYNC_OPTION_TYPE_STOP: -                ret = glusterd_op_verify_gsync_running (volinfo, slave, -                                                        op_errstr); -                break; -        } - -out: -        return ret; -}  static gf_boolean_t  glusterd_is_profile_on (glusterd_volinfo_t *volinfo) @@ -2796,6 +652,7 @@ glusterd_op_stage_stats_volume (dict_t *dict, char **op_errstr)                          ret = -1;                          goto out;                  } +          }          if ((GF_CLI_STATS_STOP == stats_op) ||              (GF_CLI_STATS_INFO == stats_op)) { @@ -2803,6 +660,7 @@ glusterd_op_stage_stats_volume (dict_t *dict, char **op_errstr)                          snprintf (msg, sizeof (msg), "Profile on Volume %s is"                                    " not started", volinfo->volname);                          ret = -1; +                          goto out;                  }          } @@ -2826,1507 +684,6 @@ out:          return ret;  } -static int -glusterd_op_create_volume (dict_t *dict, char **op_errstr) -{ -        int                   ret        = 0; -        char                 *volname    = NULL; -        glusterd_conf_t      *priv       = NULL; -        glusterd_volinfo_t   *volinfo    = NULL; -        gf_boolean_t          vol_added = _gf_false; -        glusterd_brickinfo_t *brickinfo  = NULL; -        xlator_t             *this       = NULL; -        char                 *brick      = NULL; -        int32_t               count      = 0; -        int32_t               i          = 1; -        char                 *bricks     = NULL; -        char                 *brick_list = NULL; -        char                 *free_ptr   = NULL; -        char                 *saveptr    = NULL; -        int32_t               sub_count  = 0; -        char                 *trans_type = NULL; -        char                 *str        = NULL; - -        this = THIS; -        GF_ASSERT (this); - -        priv = this->private; -        GF_ASSERT (priv); - -        ret = glusterd_volinfo_new (&volinfo); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); -                goto out; -        } - -        ret = dict_get_str (dict, "volname", &volname); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        strncpy (volinfo->volname, volname, GLUSTERD_MAX_VOLUME_NAME); -        GF_ASSERT (volinfo->volname); - -        ret = dict_get_int32 (dict, "type", &volinfo->type); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get type"); -                goto out; -        } - -        ret = dict_get_int32 (dict, "count", &volinfo->brick_count); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get count"); -                goto out; -        } - -        ret = dict_get_int32 (dict, "port", &volinfo->port); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get port"); -                goto out; -        } - -        count = volinfo->brick_count; - -        ret = dict_get_str (dict, "bricks", &bricks); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); -                goto out; -        } - -        if (GF_CLUSTER_TYPE_REPLICATE == volinfo->type) { -                ret = dict_get_int32 (dict, "replica-count", -                                      &sub_count); -                if (ret) -                        goto out; -        } else if (GF_CLUSTER_TYPE_STRIPE == volinfo->type) { -                ret = dict_get_int32 (dict, "stripe-count", -                                      &sub_count); -                if (ret) -                        goto out; -        } else if (GF_CLUSTER_TYPE_STRIPE_REPLICATE == volinfo->type) { -                ret = dict_get_int32 (dict, "stripe-count", -                                      &volinfo->stripe_count); -                if (ret) -                        goto out; -                ret = dict_get_int32 (dict, "replica-count", -                                      &volinfo->replica_count); -                if (ret) -                        goto out; - -                sub_count = volinfo->stripe_count * volinfo->replica_count; -        } - -        ret = dict_get_str (dict, "transport", &trans_type); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get transport"); -                goto out; -        } - -        ret = dict_get_str (dict, "volume-id", &str); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume-id"); -                goto out; -        } -        ret = uuid_parse (str, volinfo->volume_id); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "unable to parse uuid %s", str); -                goto out; -        } - -        if (strcasecmp (trans_type, "rdma") == 0) { -                volinfo->transport_type = GF_TRANSPORT_RDMA; -                volinfo->nfs_transport_type = GF_TRANSPORT_RDMA; -        } else if (strcasecmp (trans_type, "tcp") == 0) { -                volinfo->transport_type = GF_TRANSPORT_TCP; -                volinfo->nfs_transport_type = GF_TRANSPORT_TCP; -        } else { -                volinfo->transport_type = GF_TRANSPORT_BOTH_TCP_RDMA; -                volinfo->nfs_transport_type = GF_DEFAULT_NFS_TRANSPORT; -        } - -        volinfo->sub_count = sub_count; - -        if (bricks) { -                brick_list = gf_strdup (bricks); -                free_ptr = brick_list; -        } - -        if (count) -                brick = strtok_r (brick_list+1, " \n", &saveptr); - -        while ( i <= count) { -                ret = glusterd_brickinfo_from_brick (brick, &brickinfo); -                if (ret) -                        goto out; - -                ret = glusterd_resolve_brick (brickinfo); -                if (ret) -                        goto out; -                list_add_tail (&brickinfo->brick_list, &volinfo->bricks); -                brick = strtok_r (NULL, " \n", &saveptr); -                i++; -        } - -        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); -        if (ret) { -                glusterd_store_delete_volume (volinfo); -                *op_errstr = gf_strdup ("Failed to store the Volume information"); -                goto out; -        } - -        ret = glusterd_create_volfiles_and_notify_services (volinfo); -        if (ret) { -                *op_errstr = gf_strdup ("Failed to create volume files"); -                goto out; -        } - -        ret = glusterd_volume_compute_cksum (volinfo); -        if (ret) { -                *op_errstr = gf_strdup ("Failed to compute checksum of volume"); -                goto out; -        } - -        volinfo->defrag_status = 0; -        list_add_tail (&volinfo->vol_list, &priv->volumes); -        vol_added = _gf_true; -out: -        if (free_ptr) -                GF_FREE(free_ptr); -        if (!vol_added && volinfo) -                glusterd_volinfo_delete (volinfo); -        return ret; -} - -static int -glusterd_op_add_brick (dict_t *dict, char **op_errstr) -{ -        int                                     ret = 0; -        char                                    *volname = NULL; -        glusterd_conf_t                         *priv = NULL; -        glusterd_volinfo_t                      *volinfo = NULL; -        xlator_t                                *this = NULL; -        char                                    *bricks = NULL; -        int32_t                                 count = 0; - -        this = THIS; -        GF_ASSERT (this); - -        priv = this->private; -        GF_ASSERT (priv); - -        ret = dict_get_str (dict, "volname", &volname); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        ret = glusterd_volinfo_find (volname, &volinfo); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); -                goto out; -        } - -        ret = dict_get_int32 (dict, "count", &count); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get count"); -                goto out; -        } - - -        ret = dict_get_str (dict, "bricks", &bricks); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); -                goto out; -        } - -        ret = glusterd_op_perform_add_bricks (volinfo, count, bricks); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to add bricks"); -                goto out; -        } - -        volinfo->defrag_status = 0; - -        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); -        if (ret) -                goto out; - -        if (GLUSTERD_STATUS_STARTED == volinfo->status) -                ret = glusterd_check_generate_start_nfs (); - -out: -        return ret; -} - -static int -rb_regenerate_volfiles (glusterd_volinfo_t *volinfo, -                        glusterd_brickinfo_t *brickinfo, -                        int32_t pump_needed) -{ -        dict_t *dict = NULL; -        int ret = 0; - -        dict = volinfo->dict; - -        gf_log ("", GF_LOG_DEBUG, -                "attempting to set pump value=%d", pump_needed); - -        ret = dict_set_int32 (dict, "enable-pump", pump_needed); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "could not dict_set enable-pump"); -                goto out; -        } - -        ret = glusterd_create_rb_volfiles (volinfo, brickinfo); - -out: -        return ret; -} - -static int -rb_src_brick_restart (glusterd_volinfo_t *volinfo, -                      glusterd_brickinfo_t *src_brickinfo, -                      int activate_pump) -{ -        int                     ret = 0; - -        gf_log ("", GF_LOG_DEBUG, -                "Attempting to kill src"); - -        ret = glusterd_nfs_server_stop (); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to stop nfs, ret: %d", -                        ret); -        } - -        ret = glusterd_volume_stop_glusterfs (volinfo, src_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to stop " -                        "glusterfs, ret: %d", ret); -                goto out; -        } - -        glusterd_delete_volfile (volinfo, src_brickinfo); - -        if (activate_pump) { -                ret = rb_regenerate_volfiles (volinfo, src_brickinfo, 1); -                if (ret) { -                        gf_log ("", GF_LOG_DEBUG, -                                "Could not regenerate volfiles with pump"); -                        goto out; -                } -        } else { -                ret = rb_regenerate_volfiles (volinfo, src_brickinfo, 0); -                if (ret) { -                        gf_log ("", GF_LOG_DEBUG, -                                "Could not regenerate volfiles without pump"); -                        goto out; -                } - -        } - -        sleep (2); -        ret = glusterd_volume_start_glusterfs (volinfo, src_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to start " -                        "glusterfs, ret: %d", ret); -                goto out; -        } - -out: -        ret = glusterd_nfs_server_start (); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to start nfs, ret: %d", -                        ret); -        } -        return ret; -} - -static int -rb_send_xattr_command (glusterd_volinfo_t *volinfo, -                       glusterd_brickinfo_t *src_brickinfo, -                       glusterd_brickinfo_t *dst_brickinfo, -                       const char *xattr_key, -                       const char *value) -{ -        glusterd_conf_t  *priv                        = NULL; -        char              mount_point_path[PATH_MAX]  = {0,}; -        struct stat       buf; -        int               ret                         = -1; - -        priv = THIS->private; - -        snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", -                  priv->workdir, volinfo->volname, -                  RB_CLIENT_MOUNTPOINT); - -        ret = stat (mount_point_path, &buf); -         if (ret) { -                 gf_log ("", GF_LOG_DEBUG, -                         "stat failed. Could not send " -                         " %s command", xattr_key); -                 goto out; -         } - -        ret = sys_lsetxattr (mount_point_path, xattr_key, -                         value, -                         strlen (value) + 1, -                         0); - -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "setxattr failed"); -                goto out; -        } - -        ret = 0; - -out: -        return ret; -} - -static int -rb_spawn_dst_brick (glusterd_volinfo_t *volinfo, -                    glusterd_brickinfo_t *brickinfo) -{ -        glusterd_conf_t    *priv           = NULL; -        runner_t            runner         = {0,}; -        int                 ret            = -1; -        int32_t             port           = 0; - -        priv = THIS->private; - -        port = pmap_registry_alloc (THIS); -        brickinfo->port = port; - -        GF_ASSERT (port); - -        runinit (&runner); -        runner_add_arg (&runner, GFS_PREFIX"/sbin/glusterfs"); -        runner_argprintf (&runner, "-f" "%s/vols/%s/"RB_DSTBRICKVOL_FILENAME, -                          priv->workdir, volinfo->volname); -        runner_argprintf (&runner, "-p" "%s/vols/%s/"RB_DSTBRICK_PIDFILE, -                          priv->workdir, volinfo->volname); -        runner_add_arg (&runner, "--xlator-option"); -        runner_argprintf (&runner, "src-server.listen-port=%d", port); - -        ret = runner_run (&runner); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "Could not start glusterfs"); -                goto out; -        } - -        gf_log ("", GF_LOG_DEBUG, -                "Successfully started glusterfs: brick=%s:%s", -                brickinfo->hostname, brickinfo->path); - -        ret = 0; - -out: -        return ret; -} - -static int -rb_spawn_glusterfs_client (glusterd_volinfo_t *volinfo, -                           glusterd_brickinfo_t *brickinfo) -{ -        glusterd_conf_t    *priv           = NULL; -        char                cmd_str[8192]  = {0,}; -        runner_t            runner         = {0,}; -        struct stat         buf; -        int                 ret            = -1; - -        priv = THIS->private; - -        runinit (&runner); -        runner_add_arg (&runner, GFS_PREFIX"/sbin/glusterfs"); -        runner_argprintf (&runner, "-f" "%s/vols/%s/"RB_CLIENTVOL_FILENAME, -                          priv->workdir, volinfo->volname); -        runner_argprintf (&runner, "%s/vols/%s/"RB_CLIENT_MOUNTPOINT, -                          priv->workdir, volinfo->volname); - -        ret = runner_run (&runner); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "Could not start glusterfs"); -                goto out; -        } - -        gf_log ("", GF_LOG_DEBUG, -                "Successfully started glusterfs: brick=%s:%s", -                brickinfo->hostname, brickinfo->path); - -        memset (cmd_str, 0, sizeof (cmd_str)); - -        snprintf (cmd_str, 4096, "%s/vols/%s/%s", -                  priv->workdir, volinfo->volname, -                  RB_CLIENT_MOUNTPOINT); - -        ret = stat (cmd_str, &buf); -        if (ret) { -                 gf_log ("", GF_LOG_DEBUG, -                         "stat on mountpoint failed"); -                 goto out; -         } - -         gf_log ("", GF_LOG_DEBUG, -                 "stat on mountpoint succeeded"); - -        ret = 0; - -out: -        return ret; -} - -static const char *client_volfile_str =  "volume mnt-client\n" -        " type protocol/client\n" -        " option remote-host %s\n" -        " option remote-subvolume %s\n" -        " option remote-port %d\n" -        " option transport-type %s\n" -        "end-volume\n" -        "volume mnt-wb\n" -        " type performance/write-behind\n" -        " subvolumes mnt-client\n" -        "end-volume\n"; - -static int -rb_generate_client_volfile (glusterd_volinfo_t *volinfo, -                            glusterd_brickinfo_t *src_brickinfo) -{ -        glusterd_conf_t  *priv                  = NULL; -        FILE             *file                  = NULL; -        char              filename[PATH_MAX]    = {0, }; -        int               ret                   = -1; -        char             *ttype                 = NULL; - -        priv = THIS->private; - -        gf_log ("", GF_LOG_DEBUG, -                "Creating volfile"); - -        snprintf (filename, PATH_MAX, "%s/vols/%s/%s", -                  priv->workdir, volinfo->volname, -                  RB_CLIENTVOL_FILENAME); - -        file = fopen (filename, "w+"); -        if (!file) { -                gf_log ("", GF_LOG_DEBUG, -                        "Open of volfile failed"); -                ret = -1; -                goto out; -        } - -        GF_ASSERT (src_brickinfo->port); - -	ttype = glusterd_get_trans_type_rb (volinfo->transport_type); -	if (NULL == ttype){ -		ret = -1; -		goto out; -	} - -        fprintf (file, client_volfile_str, src_brickinfo->hostname, -                 src_brickinfo->path, src_brickinfo->port, ttype); - -        fclose (file); -        GF_FREE (ttype); - -        ret = 0; - -out: -        return ret; -} - -static const char *dst_brick_volfile_str = "volume src-posix\n" -        " type storage/posix\n" -        " option directory %s\n" -        "end-volume\n" -        "volume %s\n" -        " type features/locks\n" -        " subvolumes src-posix\n" -        "end-volume\n" -        "volume src-server\n" -        " type protocol/server\n" -        " option auth.addr.%s.allow *\n" -        " option transport-type %s\n" -        " subvolumes %s\n" -        "end-volume\n"; - -static int -rb_generate_dst_brick_volfile (glusterd_volinfo_t *volinfo, -                               glusterd_brickinfo_t *dst_brickinfo) -{ -        glusterd_conf_t    *priv                = NULL; -        FILE               *file                = NULL; -        char                filename[PATH_MAX]  = {0, }; -        int                 ret                 = -1; -        char               *trans_type          = NULL; - -        priv = THIS->private; - -        gf_log ("", GF_LOG_DEBUG, -                "Creating volfile"); - -        snprintf (filename, PATH_MAX, "%s/vols/%s/%s", -                  priv->workdir, volinfo->volname, -                  RB_DSTBRICKVOL_FILENAME); - -        file = fopen (filename, "w+"); -        if (!file) { -                gf_log ("", GF_LOG_DEBUG, -                        "Open of volfile failed"); -                ret = -1; -                goto out; -        } - -	trans_type = glusterd_get_trans_type_rb (volinfo->transport_type); -	if (NULL == trans_type){ -		ret = -1; -		goto out; -	} - -        fprintf (file, dst_brick_volfile_str, dst_brickinfo->path, -                 dst_brickinfo->path, dst_brickinfo->path, -                 trans_type, dst_brickinfo->path); - -	GF_FREE (trans_type); - -        fclose (file); - -        ret = 0; - -out: -        return ret; -} - - -static int -rb_mountpoint_mkdir (glusterd_volinfo_t *volinfo, -                     glusterd_brickinfo_t *src_brickinfo) -{ -        glusterd_conf_t *priv                       = NULL; -        char             mount_point_path[PATH_MAX] = {0,}; -        int              ret                        = -1; - -        priv = THIS->private; - -        snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", -                  priv->workdir, volinfo->volname, -                  RB_CLIENT_MOUNTPOINT); - -        ret = mkdir (mount_point_path, 0777); -        if (ret && (errno != EEXIST)) { -                gf_log ("", GF_LOG_DEBUG, "mkdir failed, errno: %d", -                        errno); -                goto out; -        } - -        ret = 0; - -out: -        return ret; -} - -static int -rb_mountpoint_rmdir (glusterd_volinfo_t *volinfo, -                     glusterd_brickinfo_t *src_brickinfo) -{ -        glusterd_conf_t *priv                       = NULL; -        char             mount_point_path[PATH_MAX] = {0,}; -        int              ret                        = -1; - -        priv = THIS->private; - -        snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", -                  priv->workdir, volinfo->volname, -                  RB_CLIENT_MOUNTPOINT); - -        ret = rmdir (mount_point_path); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, "rmdir failed"); -                goto out; -        } - -        ret = 0; - -out: -        return ret; -} - -static int -rb_destroy_maintenance_client (glusterd_volinfo_t *volinfo, -                                glusterd_brickinfo_t *src_brickinfo) -{ -        glusterd_conf_t  *priv                        = NULL; -        runner_t          runner                      = {0,}; -        char              filename[PATH_MAX]          = {0,}; -        struct stat       buf; -        char              mount_point_path[PATH_MAX]  = {0,}; -        int               ret                         = -1; - -        priv = THIS->private; - -        snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", -                  priv->workdir, volinfo->volname, -                  RB_CLIENT_MOUNTPOINT); - -        ret = stat (mount_point_path, &buf); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "stat failed. Cannot destroy maintenance " -                        "client"); -                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); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "umount failed on maintenance client"); -                goto out; -        } - -        ret = rb_mountpoint_rmdir (volinfo, src_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "rmdir of mountpoint failed"); -                goto out; -        } - -        snprintf (filename, PATH_MAX, "%s/vols/%s/%s", -                  priv->workdir, volinfo->volname, -                  RB_CLIENTVOL_FILENAME); - -        ret = unlink (filename); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "unlink failed"); -                goto out; -        } - -        ret = 0; - -out: -        return ret; -} - -static int -rb_spawn_maintenance_client (glusterd_volinfo_t *volinfo, -                             glusterd_brickinfo_t *src_brickinfo) -{ -        int ret = -1; - -        ret = rb_generate_client_volfile (volinfo, src_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, "Unable to generate client " -                        "volfile"); -                goto out; -        } - -        ret = rb_mountpoint_mkdir (volinfo, src_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, "Unable to mkdir " -                        "mountpoint"); -                goto out; -        } - -        ret = rb_spawn_glusterfs_client (volinfo, src_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, "Unable to start glusterfs"); -                goto out; -        } - -        ret = 0; -out: -        return ret; -} - -static int -rb_spawn_destination_brick (glusterd_volinfo_t *volinfo, -                            glusterd_brickinfo_t *dst_brickinfo) - -{ -        int ret = -1; - -        ret = rb_generate_dst_brick_volfile (volinfo, dst_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, "Unable to generate client " -                        "volfile"); -                goto out; -        } - -        ret = rb_spawn_dst_brick (volinfo, dst_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, "Unable to start glusterfs"); -                goto out; -        } - -        ret = 0; -out: -        return ret; -} - -static int -rb_do_operation_start (glusterd_volinfo_t *volinfo, -                       glusterd_brickinfo_t *src_brickinfo, -                       glusterd_brickinfo_t *dst_brickinfo) -{ -        char start_value[8192] = {0,}; -        int ret = -1; - - -        gf_log ("", GF_LOG_DEBUG, -                "replace-brick sending start xattr"); - -        ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "Could not spawn maintenance " -                        "client"); -                goto out; -        } - -	gf_log ("", GF_LOG_DEBUG, -		"mounted the replace brick client"); - -        snprintf (start_value, 8192, "%s:%s:%d", -                  dst_brickinfo->hostname, -                  dst_brickinfo->path, -                  dst_brickinfo->port); - - -        ret = rb_send_xattr_command (volinfo, src_brickinfo, -                                     dst_brickinfo, RB_PUMP_START_CMD, -                                     start_value); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "Failed to send command to pump"); -        } - -        ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "Failed to destroy maintenance " -                        "client"); -                goto out; -        } - -        gf_log ("", GF_LOG_DEBUG, -		"unmounted the replace brick client"); -        ret = 0; - -out: -        return ret; -} - -static int -rb_do_operation_pause (glusterd_volinfo_t *volinfo, -                       glusterd_brickinfo_t *src_brickinfo, -                       glusterd_brickinfo_t *dst_brickinfo) -{ -        int ret = -1; - -        gf_log ("", GF_LOG_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) -{ -        glusterd_conf_t  *priv               = NULL; -        char              pidfile[PATH_MAX]  = {0,}; - -        priv = THIS->private; - -        snprintf (pidfile, PATH_MAX, "%s/vols/%s/%s", -                  priv->workdir, volinfo->volname, -                  RB_DSTBRICK_PIDFILE); - -        return glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_true); -} - -static int -rb_do_operation_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); - -       ret = stat (mount_point_path, &buf); -         if (ret) { -                 gf_log ("", GF_LOG_DEBUG, -                         "stat failed. Could not send " -                         " %s command", xattr_key); -                 goto out; -         } - -        ret = sys_lgetxattr (mount_point_path, xattr_key, value, 8192); - -        if (ret < 0) { -                gf_log ("", GF_LOG_DEBUG, -                        "getxattr failed"); -                goto out; -        } - -        ret = 0; - -out: -        return ret; -} - -static int -rb_do_operation_status (glusterd_volinfo_t *volinfo, -                        glusterd_brickinfo_t *src_brickinfo, -                        glusterd_brickinfo_t *dst_brickinfo) -{ -        char            status[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; -        } - -        origin = _gf_true; - -        if (origin) { -                ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); -                if (ret) { -                        gf_log ("", GF_LOG_DEBUG, -                                "Could not spawn maintenance " -                                "client"); -                        goto out; -                } - -		gf_log ("", GF_LOG_DEBUG, -			"mounted the replace brick client"); - -                ret = rb_get_xattr_command (volinfo, src_brickinfo, -                                            dst_brickinfo, RB_PUMP_STATUS_CMD, -                                            status); -                if (ret) { -                        gf_log ("", GF_LOG_DEBUG, -                                "Failed to get status from pump"); -                        goto umount; -                } - -                gf_log ("", GF_LOG_DEBUG, -                        "pump status is %s", status); - -                status_reply = gf_strdup (status); -                if (!status_reply) { -                        gf_log ("", GF_LOG_ERROR, "Out of memory"); -                        ret = -1; -                        goto umount; -                } - -                ret = dict_set_dynstr (ctx, "status-reply", -                                       status_reply); -                if (ret) { -                        gf_log ("", GF_LOG_DEBUG, -                                "failed to set pump status in ctx"); - -                } - -	umount: -                ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); -                if (ret) { -                        gf_log ("", GF_LOG_DEBUG, -                                "Failed to destroy maintenance " -                                "client"); -			goto out; -		} -        } - -	gf_log ("", GF_LOG_DEBUG, -		"unmounted the replace brick client"); -out: -        return ret; -} - -/* Set src-brick's port number to be used in the maintainance mount - * after all commit acks are received. - */ -static int -rb_update_srcbrick_port (glusterd_brickinfo_t *src_brickinfo, dict_t *rsp_dict, -                         dict_t *req_dict, int32_t replace_op) -{ -        xlator_t *this            = NULL; -        dict_t   *ctx             = NULL; -        int       ret             = 0; -        int       dict_ret        = 0; -        int       src_port        = 0; - -        this = THIS; - -        ctx = glusterd_op_get_ctx (); -        if (ctx) { -                dict_ret = dict_get_int32 (req_dict, "src-brick-port", &src_port); -                if (src_port) -                        src_brickinfo->port = src_port; -        } - -        if (!glusterd_is_local_addr (src_brickinfo->hostname)) { -                gf_log ("", GF_LOG_INFO, -                        "adding src-brick port no"); - -                src_brickinfo->port = pmap_registry_search (this, -                                      src_brickinfo->path, GF_PMAP_PORT_BRICKSERVER); -                if (!src_brickinfo->port && -                    replace_op != GF_REPLACE_OP_COMMIT_FORCE ) { -                        gf_log ("", GF_LOG_ERROR, -                                "Src brick port not available"); -                        ret = -1; -                        goto out; -                } - -                if (rsp_dict) { -                        ret = dict_set_int32 (rsp_dict, "src-brick-port", src_brickinfo->port); -                        if (ret) { -                                gf_log ("", GF_LOG_DEBUG, -                                        "Could not set src-brick port no"); -                                goto out; -                        } -                } - -                ctx = glusterd_op_get_ctx (); -                if (ctx) { -                        ret = dict_set_int32 (ctx, "src-brick-port", src_brickinfo->port); -                        if (ret) { -                                gf_log ("", GF_LOG_DEBUG, -                                        "Could not set src-brick port no"); -                                goto out; -                        } -                } - -        } - -out: -        return ret; - -} - -static int -rb_update_dstbrick_port (glusterd_brickinfo_t *dst_brickinfo, dict_t *rsp_dict, -                         dict_t *req_dict, int32_t replace_op) -{ -        dict_t *ctx           = NULL; -        int     ret           = 0; -        int     dict_ret      = 0; -        int     dst_port      = 0; - -        ctx = glusterd_op_get_ctx (); -        if (ctx) { -                dict_ret = dict_get_int32 (req_dict, "dst-brick-port", &dst_port); -                if (dst_port) -                        dst_brickinfo->port = dst_port; - -        } - -        if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { -                gf_log ("", GF_LOG_INFO, -                        "adding dst-brick port no"); - -                if (rsp_dict) { -                        ret = dict_set_int32 (rsp_dict, "dst-brick-port", -                                              dst_brickinfo->port); -                        if (ret) { -                                gf_log ("", GF_LOG_DEBUG, -                                        "Could not set dst-brick port no in rsp dict"); -                                goto out; -                        } -                } - -                ctx = glusterd_op_get_ctx (); -                if (ctx) { -                        ret = dict_set_int32 (ctx, "dst-brick-port", -                                              dst_brickinfo->port); -                        if (ret) { -                                gf_log ("", GF_LOG_DEBUG, -                                        "Could not set dst-brick port no"); -                                goto out; -                        } -                } -        } -out: -        return ret; -} - - - -static int -glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) -{ -        int                                      ret = 0; -        dict_t                                  *ctx  = NULL; -        int                                      replace_op = 0; -        glusterd_volinfo_t                      *volinfo = NULL; -        char                                    *volname = NULL; -        xlator_t                                *this = NULL; -        glusterd_conf_t                         *priv = NULL; -        char                                    *src_brick = NULL; -        char                                    *dst_brick = NULL; -        glusterd_brickinfo_t                    *src_brickinfo = NULL; -        glusterd_brickinfo_t                    *dst_brickinfo = NULL; - -        this = THIS; -        GF_ASSERT (this); - -        priv = this->private; -        GF_ASSERT (priv); - -        ret = dict_get_str (dict, "src-brick", &src_brick); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); -                goto out; -        } - -        gf_log (this->name, GF_LOG_DEBUG, -                "src brick=%s", src_brick); - -        ret = dict_get_str (dict, "dst-brick", &dst_brick); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get dst brick"); -                goto out; -        } - -        gf_log (this->name, GF_LOG_DEBUG, -                "dst brick=%s", dst_brick); - -        ret = dict_get_str (dict, "volname", &volname); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        ret = dict_get_int32 (dict, "operation", (int32_t *)&replace_op); -        if (ret) { -                gf_log (this->name, GF_LOG_DEBUG, -                        "dict_get on operation failed"); -                goto out; -        } - -        ret = glusterd_volinfo_find (volname, &volinfo); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); -                goto out; -        } - -        ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, &src_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, "Unable to get src-brickinfo"); -                goto out; -        } - - -        ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get " -                         "replace brick destination brickinfo"); -                goto out; -        } - -        ret = glusterd_resolve_brick (dst_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); -                goto out; -        } - -        ret = rb_update_srcbrick_port (src_brickinfo, rsp_dict, -                                       dict, replace_op); -        if (ret) -                goto out; - -	if ((GF_REPLACE_OP_START != replace_op)) { -                ret = rb_update_dstbrick_port (dst_brickinfo, rsp_dict, -                                               dict, replace_op); -                if (ret) -                        goto out; -	} - -        switch (replace_op) { -        case GF_REPLACE_OP_START: -        { -                if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { -                        gf_log ("", GF_LOG_INFO, -                                "I AM THE DESTINATION HOST"); -                        if (!glusterd_is_rb_paused (volinfo)) { -                                ret = rb_spawn_destination_brick (volinfo, dst_brickinfo); -                                if (ret) { -                                        gf_log ("", GF_LOG_DEBUG, -                                                "Failed to spawn destination brick"); -                                        goto out; -                                } -                        } else { -                                gf_log ("", GF_LOG_ERROR, "Replace brick is already " -                                        "started=> no need to restart dst brick "); -                        } -		} - - -		if (!glusterd_is_local_addr (src_brickinfo->hostname)) { -		        ret = rb_src_brick_restart (volinfo, src_brickinfo, -				                    1); -		        if (ret) { -				gf_log ("", GF_LOG_DEBUG, -	                        "Could not restart src-brick"); -			        goto out; -			} -		} - -		if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { -			gf_log ("", GF_LOG_INFO, -				"adding dst-brick port no"); - -                        ret = rb_update_dstbrick_port (dst_brickinfo, rsp_dict, -                                                       dict, replace_op); -                        if (ret) -                                goto out; -                } - -                glusterd_set_rb_status (volinfo, GF_RB_STATUS_STARTED); -		break; -	} - -        case GF_REPLACE_OP_COMMIT: -        case GF_REPLACE_OP_COMMIT_FORCE: -        { -                ctx = glusterd_op_get_ctx (); -                if (ctx) { -                        ret = rb_do_operation_commit (volinfo, src_brickinfo, dst_brickinfo); -                        if (ret) { -                                gf_log ("", GF_LOG_ERROR, -                                        "Commit operation failed"); -                                goto out; -                        } -                } - -                ret = dict_set_int32 (volinfo->dict, "enable-pump", 0); -                gf_log ("", GF_LOG_DEBUG, -                        "Received commit - will be adding dst brick and " -                        "removing src brick"); - -                if (!glusterd_is_local_addr (dst_brickinfo->hostname) && -                    replace_op != GF_REPLACE_OP_COMMIT_FORCE) { -                        gf_log ("", GF_LOG_INFO, -                                "I AM THE DESTINATION HOST"); -                        ret = rb_kill_destination_brick (volinfo, dst_brickinfo); -                        if (ret) { -                                gf_log ("", GF_LOG_DEBUG, -                                        "Failed to kill destination brick"); -                                goto out; -                        } -                } - -                if (ret) { -                        gf_log ("", GF_LOG_CRITICAL, -                                "Unable to cleanup dst brick"); -                        goto out; -                } - - -                ret = glusterd_nfs_server_stop (); -                if (ret) { -                        gf_log ("", GF_LOG_ERROR, -                                "Unable to stop nfs server, ret: %d", ret); -                } - -		ret = glusterd_op_perform_replace_brick (volinfo, src_brick, -							 dst_brick); -		if (ret) { -			gf_log ("", GF_LOG_CRITICAL, "Unable to add " -				"dst-brick: %s to volume: %s", -				dst_brick, volinfo->volname); -		        (void) glusterd_check_generate_start_nfs (); -			goto out; -		} - -		volinfo->defrag_status = 0; - -		ret = glusterd_check_generate_start_nfs (); -		if (ret) { -                        gf_log ("", GF_LOG_CRITICAL, -                                "Failed to generate nfs volume file"); -		} - - -		ret = glusterd_fetchspec_notify (THIS); -                glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); -                glusterd_brickinfo_delete (volinfo->dst_brick); -                volinfo->src_brick = volinfo->dst_brick = NULL; -        } -        break; - -        case GF_REPLACE_OP_PAUSE: -        { -                gf_log ("", GF_LOG_DEBUG, -                        "Received pause - doing nothing"); -                ctx = glusterd_op_get_ctx (); -                if (ctx) { -                        ret = rb_do_operation_pause (volinfo, src_brickinfo, -                                                     dst_brickinfo); -                        if (ret) { -                                gf_log ("", GF_LOG_ERROR, -                                        "Pause operation failed"); -                                goto out; -                        } -                } - -                glusterd_set_rb_status (volinfo, GF_RB_STATUS_PAUSED); -        } -                break; - -        case GF_REPLACE_OP_ABORT: -        { - -                ctx = glusterd_op_get_ctx (); -                if (ctx) { -                        ret = rb_do_operation_abort (volinfo, src_brickinfo, dst_brickinfo); -                        if (ret) { -                                gf_log (THIS->name, GF_LOG_ERROR, -                                        "Abort operation failed"); -                                goto out; -                        } -                } - -                ret = dict_set_int32 (volinfo->dict, "enable-pump", 0); -		if (ret) { -			gf_log (THIS->name, GF_LOG_CRITICAL, "Unable to disable pump"); -		} - - -                if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { -                        gf_log (THIS->name, GF_LOG_INFO, -                                "I AM THE DESTINATION HOST"); -                        ret = rb_kill_destination_brick (volinfo, dst_brickinfo); -                        if (ret) { -                                gf_log ("", GF_LOG_DEBUG, -                                        "Failed to kill destination brick"); -                                goto out; -                        } -                } -                glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); -                glusterd_brickinfo_delete (volinfo->dst_brick); -                volinfo->src_brick = volinfo->dst_brick = NULL; -        } -        break; - -        case GF_REPLACE_OP_STATUS: -        { -                gf_log ("", GF_LOG_DEBUG, -                        "received status - doing nothing"); -                ctx = glusterd_op_get_ctx (); -                if (ctx) { -                        if (glusterd_is_rb_paused (volinfo)) { -                                ret = dict_set_str (ctx, "status-reply", -                                                 "replace brick has been paused"); -                                if (ret) -                                        gf_log (THIS->name, GF_LOG_ERROR, -                                                "failed to set pump status" -                                                "in ctx"); -                                goto out; -                        } - -                        ret = rb_do_operation_status (volinfo, src_brickinfo, -                                                      dst_brickinfo); -                        if (ret) -                                goto out; -                } - -        } -                break; - -        default: -                ret = -1; -                goto out; -        } -        if (!ret && replace_op != GF_REPLACE_OP_STATUS) -		ret = glusterd_store_volinfo (volinfo, -                                              GLUSTERD_VOLINFO_VER_AC_INCREMENT); -        if (ret) -                gf_log (THIS->name, GF_LOG_ERROR, "Couldn't store" -                        " replace brick operation's state"); - -out: -        return ret; -}  void  _delete_reconfig_opt (dict_t *this, char *key, data_t *value, void *data) @@ -4422,1247 +779,6 @@ out:  } -int -stop_gsync (char *master, char *slave, char **msg) -{ -        int32_t         ret     = 0; -        int             pfd     = -1; -        pid_t           pid     = 0; -        char            pidfile[PATH_MAX] = {0,}; -        char            buf [1024] = {0,}; -        int             i       = 0; -        glusterd_conf_t *priv = NULL; - -        GF_ASSERT (THIS); -        GF_ASSERT (THIS->private); - -        priv = THIS->private; - -        pfd = gsyncd_getpidfile (master, slave, pidfile); -        if (pfd == -2) { -                gf_log ("", GF_LOG_ERROR, GEOREP" stop validation " -                        " failed for %s & %s", master, slave); -                ret = -1; -                goto out; -        } -        if (gsync_status_byfd (pfd) == -1) { -                gf_log ("", GF_LOG_ERROR, "gsyncd b/w %s & %s is not" -                        " running", master, slave); -                if (msg) -                        *msg = gf_strdup ("Warning: "GEOREP" session was in " -                                          "corrupt  state"); -                /* monitor gsyncd already dead */ -                goto out; -        } - -        ret = read (pfd, buf, 1024); -        if (ret > 0) { -                pid = strtol (buf, NULL, 10); -                ret = kill (-pid, SIGTERM); -                if (ret) { -                        gf_log ("", GF_LOG_WARNING, -                                "failed to kill gsyncd"); -                        goto out; -                } -                for (i = 0; i < 20; i++) { -                        if (gsync_status_byfd (pfd) == -1) { -                                /* monitor gsyncd is dead but worker may -                                 * still be alive, give some more time -                                 * before SIGKILL (hack) -                                 */ -                                usleep (50000); -                                break; -                        } -                        usleep (50000); -                } -                kill (-pid, SIGKILL); -                unlink (pidfile); -        } -        ret = 0; - -out: -        close (pfd); -        return ret; -} - -int -glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave, -                                      dict_t *resp_dict); - -int -glusterd_gsync_configure (glusterd_volinfo_t *volinfo, char *slave, -                          dict_t *dict, dict_t *resp_dict, char **op_errstr) -{ -        int32_t         ret     = -1; -        char            *op_name = NULL; -        char            *op_value = NULL; -        runner_t        runner    = {0,}; -        glusterd_conf_t *priv   = NULL; -        char            *subop  = NULL; -        char            *master = NULL; - -        GF_ASSERT (slave); -        GF_ASSERT (op_errstr); -        GF_ASSERT (dict); -        GF_ASSERT (resp_dict); - -        ret = dict_get_str (dict, "subop", &subop); -        if (ret != 0) -                goto out; - -        if (strcmp (subop, "get") == 0 || strcmp (subop, "get-all") == 0) { -                /* deferred to cli */ -                gf_log ("", GF_LOG_DEBUG, "Returning 0"); -                return 0; -        } - -        ret = dict_get_str (dict, "op_name", &op_name); -        if (ret != 0) -                goto out; - -        if (strcmp (subop, "set") == 0) { -                ret = dict_get_str (dict, "op_value", &op_value); -                if (ret != 0) -                        goto out; -        } - -        if (THIS) -                priv = THIS->private; -        if (priv == NULL) { -                gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); -                *op_errstr = gf_strdup ("glusterd defunct"); -                goto out; -        } - -        master = ""; -        runinit (&runner); -        runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); -        runner_argprintf (&runner, "%s/"GSYNC_CONF, priv->workdir); -        if (volinfo) { -                master = volinfo->volname; -                runner_argprintf (&runner, ":%s", master); -        } -        runner_add_arg (&runner, slave); -        runner_argprintf (&runner, "--config-%s", subop); -        runner_add_arg (&runner, op_name); -        if (op_value) -                runner_add_arg (&runner, op_value); -        ret = runner_run (&runner); -        if (ret) { -                gf_log ("", GF_LOG_WARNING, "gsyncd failed to " -                        "%s %s option for %s %s peers", -                        subop, op_name, master, slave); - -                gf_asprintf (op_errstr, GEOREP" config-%s failed for %s %s", -                             subop, master, slave); - -                goto out; -        } -        ret = 0; -        gf_asprintf (op_errstr, "config-%s successful", subop); - -out: -        if (!ret && volinfo) { -                ret = glusterd_check_restart_gsync_session (volinfo, slave, -                                                            resp_dict); -                if (ret) -                        *op_errstr = gf_strdup ("internal error"); -        } - -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; -} - -int -glusterd_gsync_read_frm_status (char *path, char *data) -{ -        int                 ret = 0; -        FILE               *status_file = NULL; - -        GF_ASSERT (path); -        GF_ASSERT (data); -        status_file = fopen (path, "r"); -        if (status_file  == NULL) { -                gf_log ("", GF_LOG_WARNING, "Unable to read gsyncd status" -                        " file"); -                return -1; -        } -        ret = fread (data, PATH_MAX, 1, status_file); -        if (ret < 0) { -                gf_log ("", GF_LOG_WARNING, "Status file of gsyncd is corrupt"); -                return -1; -        } - -        data[strlen(data)-1] = '\0'; - -        return 0; -} - -int -glusterd_read_status_file (char *master, char *slave, -                           dict_t *dict) -{ -        glusterd_conf_t  *priv = NULL; -        int              ret = 0; -        char             statusfile[PATH_MAX] = {0, }; -        char             buff[PATH_MAX] = {0, }; -        char             mst[PATH_MAX] = {0, }; -        char             slv[PATH_MAX] = {0, }; -        char             sts[PATH_MAX] = {0, }; -        int              gsync_count = 0; -        int              status = 0; - -        GF_ASSERT (THIS); -        GF_ASSERT (THIS->private); - -        priv = THIS->private; -        ret = glusterd_gsync_get_param_file (statusfile, "state", master, -                                             slave, priv->workdir); -        if (ret) { -                gf_log ("", GF_LOG_WARNING, "Unable to get the name of status" -                        "file for %s(master), %s(slave)", master, slave); -                goto out; - -        } - -        ret = gsync_status (master, slave, &status); -        if (ret == 0 && status == -1) { -                strncpy (buff, "corrupt", sizeof (buff)); -                goto done; -        } else if (ret == -1) -                goto out; - -        ret = glusterd_gsync_read_frm_status (statusfile, buff); -        if (ret) { -                gf_log ("", GF_LOG_WARNING, "Unable to read the status" -                        "file for %s(master), %s(slave)", master, slave); -                goto out; - -        } - - done: -        ret = dict_get_int32 (dict, "gsync-count", &gsync_count); - -        if (ret) -                gsync_count = 1; -        else -                gsync_count++; - -        snprintf (mst, sizeof (mst), "master%d", gsync_count); -        ret = dict_set_dynstr (dict, mst, gf_strdup (master)); -        if (ret) -                goto out; - -        snprintf (slv, sizeof (slv), "slave%d", gsync_count); -        ret = dict_set_dynstr (dict, slv, gf_strdup (slave)); -        if (ret) -                goto out; - -        snprintf (sts, sizeof (slv), "status%d", gsync_count); -        ret = dict_set_dynstr (dict, sts, gf_strdup (buff)); -        if (ret) -                goto out; -        ret = dict_set_int32 (dict, "gsync-count", gsync_count); -        if (ret) -                goto out; - -        ret = 0; - out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d ", ret); -        return ret; -} - -int -glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave, -                                      dict_t *resp_dict) -{ - -        int                    ret = 0; -        uuid_t                 uuid = {0, }; -        glusterd_conf_t        *priv = NULL; -        char                   *status_msg = NULL; - -        GF_ASSERT (volinfo); -        GF_ASSERT (slave); -        GF_ASSERT (THIS); -        GF_ASSERT (THIS->private); - -        priv = THIS->private; - -        if (glusterd_gsync_get_uuid (slave, volinfo, uuid)) -                /* session does not exist, nothing to do */ -                goto out; -        if (uuid_compare (priv->uuid, uuid) == 0) { -                ret = stop_gsync (volinfo->volname, slave, &status_msg); -                if (ret == 0 && status_msg) -                        ret = dict_set_str (resp_dict, "gsync-status", -                                            status_msg); -                if (ret == 0) -                        ret = glusterd_start_gsync (volinfo, slave, -                                                    uuid_utoa(priv->uuid), NULL); -        } - - out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; -} - -int32_t -glusterd_marker_create_volfile (glusterd_volinfo_t *volinfo) -{ -        int32_t          ret     = 0; - -        ret = glusterd_create_volfiles_and_notify_services (volinfo); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to create volfile" -                        " for setting of marker while '"GEOREP" start'"); -                ret = -1; -                goto out; -        } - -        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); -        if (ret) -                goto out; - -        if (GLUSTERD_STATUS_STARTED == volinfo->status) -                ret = glusterd_check_generate_start_nfs (); -        ret = 0; -out: -        return ret; -} - -int -glusterd_set_marker_gsync (glusterd_volinfo_t *volinfo) -{ -        int                      ret     = -1; -        int                      marker_set = _gf_false; -        char                    *gsync_status = NULL; -        glusterd_conf_t         *priv = NULL; - -        GF_ASSERT (THIS); -        GF_ASSERT (THIS->private); - -        priv = THIS->private; - -        marker_set = glusterd_volinfo_get_boolean (volinfo, VKEY_MARKER_XTIME); -        if (marker_set == -1) { -                gf_log ("", GF_LOG_ERROR, "failed to get the marker status"); -                ret = -1; -                goto out; -        } - -        if (marker_set == _gf_false) { -                gsync_status = gf_strdup ("on"); -                if (gsync_status == NULL) { -                        ret = -1; -                        goto out; -                } - -                ret = glusterd_gsync_volinfo_dict_set (volinfo, -                                                       VKEY_MARKER_XTIME, gsync_status); -                if (ret < 0) -                        goto out; - -                ret = glusterd_marker_create_volfile (volinfo); -                if (ret) { -                        gf_log ("", GF_LOG_ERROR, "Setting dict failed"); -                        goto out; -                } -        } -        ret = 0; - -out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; -} - - - - -int -glusterd_get_gsync_status_mst_slv( glusterd_volinfo_t *volinfo, -                                   char *slave, dict_t *rsp_dict) -{ -        uuid_t             uuid = {0, }; -        glusterd_conf_t    *priv = NULL; -        int                ret = 0; - -        GF_ASSERT (volinfo); -        GF_ASSERT (slave); -        GF_ASSERT (THIS); -        GF_ASSERT (THIS->private); - -        priv = THIS->private; - -        ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); -        if ((ret == 0) && (uuid_compare (priv->uuid, uuid) != 0)) -                goto out; - -        if (ret) { -                ret = 0; -                gf_log ("", GF_LOG_INFO, "geo-replication status %s %s :" -                        "session is not active", volinfo->volname, slave); -                goto out; -        } - -        ret = glusterd_read_status_file (volinfo->volname, slave, rsp_dict); - out: -        gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); -        return ret; -} - -static int -glusterd_get_gsync_status_mst (glusterd_volinfo_t *volinfo, dict_t *rsp_dict) -{ -        glusterd_gsync_status_temp_t  param = {0, }; - -        GF_ASSERT (volinfo); - -        param.rsp_dict = rsp_dict; -        param.volinfo = volinfo; -        dict_foreach (volinfo->gsync_slaves, _get_status_mst_slv, ¶m); - -        return 0; -} - -static int -glusterd_get_gsync_status_all ( dict_t *rsp_dict) -{ - -        int32_t                 ret = 0; -        glusterd_conf_t         *priv = NULL; -        glusterd_volinfo_t      *volinfo = NULL; - -        GF_ASSERT (THIS); -        priv = THIS->private; - -        GF_ASSERT (priv); - -        list_for_each_entry (volinfo, &priv->volumes, vol_list) { -                ret = glusterd_get_gsync_status_mst (volinfo, rsp_dict); -                if (ret) -                        goto out; -        } - -out: -        gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); -        return ret; - -} - -static int -glusterd_get_gsync_status (dict_t *dict, char **op_errstr, dict_t *rsp_dict) -{ -        char               *slave  = NULL; -        char               *volname = NULL; -        char               errmsg[PATH_MAX] = {0, }; -        gf_boolean_t       exists = _gf_false; -        glusterd_volinfo_t *volinfo = NULL; -        int                ret = 0; - - -        ret = dict_get_str (dict, "master", &volname); -        if (ret < 0){ -                ret = glusterd_get_gsync_status_all (rsp_dict); -                goto out; -        } - -        exists = glusterd_check_volume_exists (volname); -        ret = glusterd_volinfo_find (volname, &volinfo); -        if ((ret) || (!exists)) { -                gf_log ("", GF_LOG_WARNING, "volume name does not exist"); -                snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" -                          " exist", volname); -                *op_errstr = gf_strdup (errmsg); -                ret = -1; -                goto out; -        } - - -        ret = dict_get_str (dict, "slave", &slave); -        if (ret < 0) { -                ret = glusterd_get_gsync_status_mst (volinfo, rsp_dict); -                goto out; -        } - -        ret = glusterd_get_gsync_status_mst_slv (volinfo, slave, rsp_dict); - - out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; - - -} - - -int -glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict) -{ -        int32_t             ret     = -1; -        int32_t             type    = -1; -        dict_t             *ctx    = NULL; -        dict_t             *resp_dict = NULL; -        char               *host_uuid = NULL; -        char               *slave  = NULL; -        char               *volname = NULL; -        glusterd_volinfo_t *volinfo = NULL; -        glusterd_conf_t    *priv = NULL; -        char               *status_msg = NULL; -        uuid_t              uuid = {0, }; - -        GF_ASSERT (THIS); -        GF_ASSERT (THIS->private); -        GF_ASSERT (dict); -        GF_ASSERT (op_errstr); - -        priv = THIS->private; - -        ret = dict_get_int32 (dict, "type", &type); -        if (ret < 0) -                goto out; - -        ret = dict_get_str (dict, "host-uuid", &host_uuid); -        if (ret < 0) -                goto out; - -        ctx = glusterd_op_get_ctx (); -        resp_dict = ctx ? ctx : rsp_dict; -        GF_ASSERT (resp_dict); - -        if (type == GF_GSYNC_OPTION_TYPE_STATUS) { -                ret = glusterd_get_gsync_status (dict, op_errstr, resp_dict); -                goto out; -        } - -        ret = dict_get_str (dict, "slave", &slave); -        if (ret < 0) -                goto out; - -        if (dict_get_str (dict, "master", &volname) == 0) { -                ret = glusterd_volinfo_find (volname, &volinfo); -                if (ret) { -                        gf_log ("", GF_LOG_WARNING, "Volinfo for %s (master) not found", -                                volname); -                        goto out; -                } -        } - -        if (type == GF_GSYNC_OPTION_TYPE_CONFIG) { -                ret = glusterd_gsync_configure (volinfo, slave, dict, resp_dict, -                                                op_errstr); -                goto out; -        } - -        if (!volinfo) { -                ret = -1; -                goto out; -        } - -        if (type == GF_GSYNC_OPTION_TYPE_START) { - -                ret = glusterd_set_marker_gsync (volinfo); -                if (ret != 0) { -                        gf_log ("", GF_LOG_WARNING, "marker start failed"); -                        *op_errstr = gf_strdup ("failed to initialize indexing"); -                        ret = -1; -                        goto out; -                } -                ret = glusterd_store_slave_in_info(volinfo, slave, -                                                   host_uuid, op_errstr); -                if (ret) -                        goto out; - -                ret = glusterd_start_gsync (volinfo, slave, host_uuid, -                                            op_errstr); -        } - -        if (type == GF_GSYNC_OPTION_TYPE_STOP) { - -                ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); -                if (ret) { -                        gf_log ("", GF_LOG_WARNING, GEOREP" is not set up for" -                                "%s(master) and %s(slave)", volname, slave); -                        *op_errstr = strdup (GEOREP" is not set up"); -                        goto out; -                } - -                ret = glusterd_remove_slave_in_info(volinfo, slave, op_errstr); -                if (ret) -                        goto out; - -                if (uuid_compare (priv->uuid, uuid) != 0) { -                        goto out; -                } - -                ret = stop_gsync (volname, slave, &status_msg); -                if (ret == 0 && status_msg) -                        ret = dict_set_str (resp_dict, "gsync-status", -                                            status_msg); -                if (ret != 0) -                        *op_errstr = gf_strdup ("internal error"); -        } - -out: -        gf_log ("", GF_LOG_DEBUG,"Returning %d", ret); -        return ret; -} - -int32_t -glusterd_check_if_quota_trans_enabled (glusterd_volinfo_t *volinfo) -{ -        int32_t  ret           = 0; -        int      flag          = _gf_false; - -        flag = glusterd_volinfo_get_boolean (volinfo, VKEY_FEATURES_QUOTA); -        if (flag == -1) { -                gf_log ("", GF_LOG_ERROR, "failed to get the quota status"); -                ret = -1; -                goto out; -        } - -        if (flag == _gf_false) { -                gf_log ("", GF_LOG_ERROR, "first enable the quota translator"); -                ret = -1; -                goto out; -        } -        ret = 0; -out: -        return ret; -} - -/* At the end of the function, the variable found will be set - * to true if the path to be removed was present in the limit-list, - * else will be false. - */ -int32_t -_glusterd_quota_remove_limits (char **quota_limits, char *path, -                               gf_boolean_t *found) -{ -        int      ret      = 0; -        int      i        = 0; -        int      size     = 0; -        int      len      = 0; -        int      pathlen  = 0; -        int      skiplen  = 0; -        int      flag     = 0; -        char    *limits   = NULL; -        char    *qlimits  = NULL; - -        if (found != NULL) -                *found = _gf_false; - -        if (*quota_limits == NULL) -                return -1; - -        qlimits = *quota_limits; - -        pathlen = strlen (path); - -        len = strlen (qlimits); - -        limits = GF_CALLOC (len + 1, sizeof (char), gf_gld_mt_char); -        if (!limits) -                return -1; - -        while (i < len) { -                if (!memcmp ((void *) &qlimits [i], (void *)path, pathlen)) -                        if (qlimits [i + pathlen] == ':') { -                                flag = 1; -                                if (found != NULL) -                                        *found = _gf_true; -                        } - -                while (qlimits [i + size] != ',' && -                       qlimits [i + size] != '\0') -                        size++; - -                if (!flag) { -                        memcpy ((void *) &limits [i], (void *) &qlimits [i], size + 1); -                } else { -                        skiplen = size + 1; -                        size = len - i - size; -                        memcpy ((void *) &limits [i], (void *) &qlimits [i + skiplen], size); -                        break; -                } - -                i += size + 1; -                size = 0; -        } - -        if (!flag) { -                ret = 1; -        } else { -                len = strlen (limits); - -                if (len == 0) { -                        GF_FREE (qlimits); - -                        *quota_limits = NULL; - -                        goto out; -                } - -                if (limits[len - 1] == ',') { -                        limits[len - 1] = '\0'; -                        len --; -                } - -                GF_FREE (qlimits); - -                qlimits = GF_CALLOC (len + 1, sizeof (char), gf_gld_mt_char); - -                if (!qlimits) { -                        ret = -1; -                        goto out; -                } - -                memcpy ((void *) qlimits, (void *) limits, len + 1); - -                *quota_limits = qlimits; - -                ret = 0; -        } - -out: -        if (limits) -                GF_FREE (limits); - -        return ret; -} - -int32_t -glusterd_quota_initiate_fs_crawl (glusterd_conf_t *priv, char *volname) -{ -        int32_t   ret = 0; -        pid_t     pid; -        char      mountdir [] = "/tmp/mntXXXXXX"; -        runner_t  runner = {0,}; -        int       status = 0; - -        if (mkdtemp (mountdir) == NULL) { -                gf_log ("glusterd", GF_LOG_DEBUG, -                        "failed to create a temporary mount directory"); -                ret = -1; -                goto out; -        } - -        runinit (&runner); -        runner_add_args (&runner, GFS_PREFIX"/sbin/glusterfs", "-s", -                         "localhost", "--volfile-id", volname, "-l", -                         DEFAULT_LOG_FILE_DIRECTORY"/quota-crawl.log", -                         mountdir, NULL); - -        ret = runner_run_reuse (&runner); -        if (ret == -1) { -                runner_log (&runner, "glusterd", GF_LOG_DEBUG, "command failed"); -                runner_end (&runner); -                goto out; -        } -        runner_end (&runner); - -        if ((pid = fork ()) < 0) { -                gf_log ("glusterd", GF_LOG_WARNING, "fork from parent failed"); -                ret = -1; -                goto out; -        } else if (pid == 0) {//first child -                /* fork one more to not hold back main process on -                 * blocking call below -                 */ -                pid = fork (); -                if (pid) -                        _exit (pid > 0 ? EXIT_SUCCESS : EXIT_FAILURE); - -                ret = chdir (mountdir); -                if (ret == -1) { -                        gf_log ("glusterd", GF_LOG_WARNING, "chdir %s failed, " -                                "reason: %s", mountdir, strerror (errno)); -                        exit (EXIT_FAILURE); -                } -                runinit (&runner); -                runner_add_args (&runner, "/usr/bin/find", "find", ".", NULL); -                if (runner_start (&runner) == -1) -                        _exit (EXIT_FAILURE); - -#ifndef GF_LINUX_HOST_OS -                runner_end (&runner); /* blocks in waitpid */ -                runcmd ("umount", mountdir, NULL); -#else -                runcmd ("umount", "-l", mountdir, NULL); -#endif -                rmdir (mountdir); -                _exit (EXIT_SUCCESS); -        } -        ret = (waitpid (pid, &status, 0) == pid && -               WIFEXITED (status) && WEXITSTATUS (status) == EXIT_SUCCESS) ? 0 : -1; - -out: -        return ret; -} - -char * -glusterd_quota_get_limit_value (char *quota_limits, char *path) -{ -        int32_t i, j, k, l, len; -        int32_t pat_len, diff; -        char   *ret_str = NULL; - -        len = strlen (quota_limits); -        pat_len = strlen (path); -        i = 0; -        j = 0; - -        while (i < len) { -                j = i; -                k = 0; -                while (path [k] == quota_limits [j]) { -                        j++; -                        k++; -                } - -                l = j; - -                while (quota_limits [j] != ',' && -                       quota_limits [j] != '\0') -                        j++; - -                if (quota_limits [l] == ':' && pat_len == (l - i)) { -                        diff = j - i; -                        ret_str = GF_CALLOC (diff + 1, sizeof (char), -                                             gf_gld_mt_char); - -                        strncpy (ret_str, "a_limits [i], diff); - -                        break; -                } -                i = ++j; //skip ',' -        } - -        return ret_str; -} - -char* -_glusterd_quota_get_limit_usages (glusterd_volinfo_t *volinfo, -                                  char *path, char **op_errstr) -{ -        int32_t  ret          = 0; -        char    *quota_limits = NULL; -        char    *ret_str      = NULL; - -        if (volinfo == NULL) -                return NULL; - -        ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, -                                    "a_limits); -        if (ret) -                return NULL; -        if (quota_limits == NULL) { -                ret_str = NULL; -                *op_errstr = gf_strdup ("Limit not set on any directory"); -        } else if (path == NULL) -                ret_str = gf_strdup (quota_limits); -        else -                ret_str = glusterd_quota_get_limit_value (quota_limits, path); - -        return ret_str; -} - -int32_t -glusterd_quota_get_limit_usages (glusterd_conf_t *priv, -                                 glusterd_volinfo_t *volinfo, -                                 char *volname, -                                 dict_t *dict, -                                 char **op_errstr) -{ -        int32_t i               = 0; -        int32_t ret             = 0; -        int32_t count           = 0; -        char    *path           = NULL; -        dict_t  *ctx            = NULL; -        char    cmd_str [1024]  = {0, }; -        char   *ret_str         = NULL; - -        ctx = glusterd_op_get_ctx (); -        if (ctx == NULL) -                return 0; - -        ret = dict_get_int32 (dict, "count", &count); -        if (ret < 0) -                goto out; - -        if (count == 0) { -                ret_str = _glusterd_quota_get_limit_usages (volinfo, NULL, -                                                            op_errstr); -        } else { -                i = 0; -                while (count--) { -                        snprintf (cmd_str, 1024, "path%d", i++); - -                        ret = dict_get_str (dict, cmd_str, &path); -                        if (ret < 0) -                                goto out; - -                        ret_str = _glusterd_quota_get_limit_usages (volinfo, path, op_errstr); -                } -        } - -        if (ret_str) { -                ret = dict_set_dynstr (ctx, "limit_list", ret_str); -        } -out: -        return ret; -} - -int32_t -glusterd_quota_enable (glusterd_volinfo_t *volinfo, char **op_errstr, -                       gf_boolean_t *crawl) -{ -        int32_t         ret     = -1; -        char            *quota_status = NULL; - -        GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); -        GF_VALIDATE_OR_GOTO ("glusterd", crawl, out); -        GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); - -        if (glusterd_is_volume_started (volinfo) == 0) { -                *op_errstr = gf_strdup ("Volume is stopped, start volume " -                                        "to enable quota."); -                goto out; -        } - -        ret = glusterd_check_if_quota_trans_enabled (volinfo); -        if (ret == 0) { -                *op_errstr = gf_strdup ("Quota is already enabled"); -                goto out; -        } - -        quota_status = gf_strdup ("on"); -        if (!quota_status) { -                gf_log ("", GF_LOG_ERROR, "memory allocation failed"); -                *op_errstr = gf_strdup ("Enabling quota has been unsuccessful"); -                goto out; -        } - -        ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, quota_status); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "dict set failed"); -                *op_errstr = gf_strdup ("Enabling quota has been unsuccessful"); -                goto out; -        } - -        *op_errstr = gf_strdup ("Enabling quota has been successful"); - -        *crawl = _gf_true; - -        ret = 0; -out: -        return ret; -} - -int32_t -glusterd_quota_disable (glusterd_volinfo_t *volinfo, char **op_errstr) -{ -        int32_t  ret            = -1; -        char    *quota_status   = NULL, *quota_limits = NULL; - -        GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); -        GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); - -        ret = glusterd_check_if_quota_trans_enabled (volinfo); -        if (ret == -1) { -                *op_errstr = gf_strdup ("Quota is already disabled"); -                goto out; -        } - -        quota_status = gf_strdup ("off"); -        if (!quota_status) { -                gf_log ("", GF_LOG_ERROR, "memory allocation failed"); -                *op_errstr = gf_strdup ("Disabling quota has been unsuccessful"); -                goto out; -        } - -        ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, quota_status); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "dict set failed"); -                *op_errstr = gf_strdup ("Disabling quota has been unsuccessful"); -                goto out; -        } - -        *op_errstr = gf_strdup ("Disabling quota has been successful"); - -        ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, -                                    "a_limits); -        if (ret) { -                gf_log ("", GF_LOG_WARNING, "failed to get the quota limits"); -        } else { -                GF_FREE (quota_limits); -        } - -        dict_del (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE); - -out: -        return ret; -} - -int32_t -glusterd_quota_limit_usage (glusterd_volinfo_t *volinfo, dict_t *dict, char **op_errstr) -{ -        int32_t          ret    = -1; -        char            *path   = NULL; -        char            *limit  = NULL; -        char            *value  = NULL; -        char             msg [1024] = {0,}; -        char            *quota_limits = NULL; - -        GF_VALIDATE_OR_GOTO ("glusterd", dict, out); -        GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); -        GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); - -        ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, -                                    "a_limits); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "failed to get the quota limits"); -                *op_errstr = gf_strdup ("failed to set limit"); -                goto out; -        } - -        ret = dict_get_str (dict, "path", &path); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); -                *op_errstr = gf_strdup ("failed to set limit"); -                goto out; -        } - -        ret = dict_get_str (dict, "limit", &limit); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); -                *op_errstr = gf_strdup ("failed to set limit"); -                goto out; -        } - -        if (quota_limits) { -                ret = _glusterd_quota_remove_limits ("a_limits, path, NULL); -                if (ret == -1) { -                        gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); -                        *op_errstr = gf_strdup ("failed to set limit"); -                        goto out; -                } -        } - -        if (quota_limits == NULL) { -                ret = gf_asprintf (&value, "%s:%s", path, limit); -                if (ret == -1) { -                        gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); -                        *op_errstr = gf_strdup ("failed to set limit"); -                        goto out; -                } -        } else { -                ret = gf_asprintf (&value, "%s,%s:%s", -                                   quota_limits, path, limit); -                if (ret == -1) { -                        gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); -                        *op_errstr = gf_strdup ("failed to set limit"); -                        goto out; -                } - -                GF_FREE (quota_limits); -        } - -        quota_limits = value; - -        ret = dict_set_str (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE, -                            quota_limits); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to set quota limits" ); -                *op_errstr = gf_strdup ("failed to set limit"); -                goto out; -        } -        snprintf (msg, 1024, "limit set on %s", path); -        *op_errstr = gf_strdup (msg); - -        ret = 0; -out: -        return ret; -} - -int32_t -glusterd_quota_remove_limits (glusterd_volinfo_t *volinfo, dict_t *dict, char **op_errstr) -{ -        int32_t         ret                   = -1; -        char            str [PATH_MAX + 1024] = {0,}; -        char            *quota_limits         = NULL; -        char            *path                 = NULL; -        gf_boolean_t     flag                 = _gf_false; - -        GF_VALIDATE_OR_GOTO ("glusterd", dict, out); -        GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); -        GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); - -        ret = glusterd_check_if_quota_trans_enabled (volinfo); -        if (ret == -1) { -                *op_errstr = gf_strdup ("Quota is disabled, please enable quota"); -                goto out; -        } - -        ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, -                                    "a_limits); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "failed to get the quota limits"); -                goto out; -        } - -        ret = dict_get_str (dict, "path", &path); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); -                goto out; -        } - -        ret = _glusterd_quota_remove_limits ("a_limits, path, &flag); -        if (ret == -1) { -                if (flag == _gf_true) -                        snprintf (str, sizeof (str), "Removing limit on %s has " -                                  "been unsuccessful", path); -                else -                        snprintf (str, sizeof (str), "%s has no limit set", path); -                *op_errstr = gf_strdup (str); -                goto out; -        } else { -                if (flag == _gf_true) -                        snprintf (str, sizeof (str), "Removed quota limit on " -                                  "%s", path); -                else -                        snprintf (str, sizeof (str), "no limit set on %s", -                                  path); -                *op_errstr = gf_strdup (str); -        } - -        if (quota_limits) { -                ret = dict_set_str (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE, -                                    quota_limits); -                if (ret) { -                        gf_log ("", GF_LOG_ERROR, "Unable to set quota limits" ); -                        goto out; -                } -        } else { -               dict_del (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE); -        } - -        ret = 0; - -out: -        return ret; -} - - -int -glusterd_op_quota (dict_t *dict, char **op_errstr) -{ -        glusterd_volinfo_t     *volinfo      = NULL; -        int32_t                 ret          = -1; -        char                   *volname      = NULL; -        dict_t                 *ctx          = NULL; -        int                     type         = -1; -        gf_boolean_t            start_crawl  = _gf_false; -        glusterd_conf_t        *priv         = NULL; - -        GF_ASSERT (dict); -        GF_ASSERT (op_errstr); - -        priv = THIS->private; - -        ret = dict_get_str (dict, "volname", &volname); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name " ); -                goto out; -        } - -        ret = glusterd_volinfo_find (volname, &volinfo); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); -                goto out; -        } - -        ret = dict_get_int32 (dict, "type", &type); - -        if (type == GF_QUOTA_OPTION_TYPE_ENABLE) { -                ret = glusterd_quota_enable (volinfo, op_errstr, &start_crawl); -                if (ret < 0) -                        goto out; - -                goto create_vol; -        } - -        if (type == GF_QUOTA_OPTION_TYPE_DISABLE) { -                ret = glusterd_quota_disable (volinfo, op_errstr); -                if (ret < 0) -                        goto out; - -                goto create_vol; -        } - -        if (type == GF_QUOTA_OPTION_TYPE_LIMIT_USAGE) { -                ret = glusterd_quota_limit_usage (volinfo, dict, op_errstr); -                if (ret < 0) -                        goto out; - -                goto create_vol; -        } - -        if (type == GF_QUOTA_OPTION_TYPE_REMOVE) { -                ret = glusterd_quota_remove_limits (volinfo, dict, op_errstr); -                if (ret < 0) -                        goto out; - -                goto create_vol; -        } - -        if (type == GF_QUOTA_OPTION_TYPE_LIST) { -                ret = glusterd_check_if_quota_trans_enabled (volinfo); -                if (ret == -1) { -                        *op_errstr = gf_strdup ("cannot list the limits, " -                                                "quota is disabled"); -                        goto out; -                } - -                ret = glusterd_quota_get_limit_usages (priv, volinfo, volname, -                                                       dict, op_errstr); - -                goto out; -        } -create_vol: -        ret = glusterd_create_volfiles_and_notify_services (volinfo); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to re-create volfile for" -                                          " 'quota'"); -                ret = -1; -                goto out; -        } - -        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); -        if (ret) -                goto out; - -        if (GLUSTERD_STATUS_STARTED == volinfo->status) -                ret = glusterd_check_generate_start_nfs (); - -        ret = 0; - -out: -        ctx = glusterd_op_get_ctx (); -        if (ctx && start_crawl == _gf_true) -                glusterd_quota_initiate_fs_crawl (priv, volname); - -        if (ctx && *op_errstr) { -                ret = dict_set_dynstr (ctx, "errstr", *op_errstr); -                if (ret) { -                        GF_FREE (*op_errstr); -                        gf_log ("", GF_LOG_DEBUG, -                                "failed to set error message in ctx"); -                } -                *op_errstr = NULL; -        } - -        return ret; -}  int  glusterd_stop_bricks (glusterd_volinfo_t *volinfo) @@ -5710,78 +826,6 @@ glusterd_restart_brick_servers (glusterd_volinfo_t *volinfo)  }  static int -glusterd_op_log_level (dict_t *dict) -{ -        int32_t             ret           = -1; -        glusterd_volinfo_t *volinfo       = NULL; -        char               *volname       = NULL; -        char               *xlator        = NULL; -        char               *loglevel      = NULL; -        xlator_t           *this          = NULL; -        glusterd_conf_t    *priv          = NULL; - -        this = THIS; -        GF_ASSERT (this); - -        priv = this->private; -        GF_ASSERT (priv); - -        ret = dict_get_str (dict, "volname", &volname); -        if (ret) { -                gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        ret = dict_get_str (dict, "xlator", &xlator); -        if (ret) { -                gf_log ("glusterd", GF_LOG_ERROR, "Unable to get translator name"); -                goto out; -        } - -        ret = dict_get_str (dict, "loglevel", &loglevel); -        if (ret) { -                gf_log ("glusterd", GF_LOG_ERROR, "Unable to get Loglevel to use"); -                goto out; -        } - -        ret = glusterd_volinfo_find (volname, &volinfo); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Cannot find volume: %s", volname); -                goto out; -        } - -        xlator = gf_strdup (xlator); - -        ret = dict_set_dynstr (volinfo->dict, "xlator", xlator); -        if (ret) -                goto out; - -        loglevel = gf_strdup (loglevel); - -        ret = dict_set_dynstr (volinfo->dict, "loglevel", loglevel); -        if (ret) -                goto out; - -        ret = glusterd_create_volfiles_and_notify_services (volinfo); -        if (ret) { -                gf_log ("glusterd", GF_LOG_ERROR, "Unable to create volfile for command" -                        " 'log level'"); -                ret = -1; -                goto out; -        } - -        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); -        if (ret) -                goto out; - -        ret = 0; - - out: -        gf_log ("glusterd", GF_LOG_DEBUG, "(cli log level) Returning: %d", ret); -        return ret; -} - -static int  glusterd_volset_help (dict_t *dict)  {          int                     ret = -1; @@ -5995,421 +1039,6 @@ glusterd_op_set_volume (dict_t *dict)          return ret;  } -static int -glusterd_op_remove_brick (dict_t *dict) -{ -        int                                     ret = -1; -        char                                    *volname = NULL; -        glusterd_volinfo_t                      *volinfo = NULL; -        char                                    *brick = NULL; -        int32_t                                 count = 0; -        int32_t                                 i = 1; -        char                                    key[256] = {0,}; - -        ret = dict_get_str (dict, "volname", &volname); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        ret = glusterd_volinfo_find (volname, &volinfo); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); -                goto out; -        } - -        ret = dict_get_int32 (dict, "count", &count); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get count"); -                goto out; -        } - - -        while ( i <= count) { -                snprintf (key, 256, "brick%d", i); -                ret = dict_get_str (dict, key, &brick); -                if (ret) { -                        gf_log ("", GF_LOG_ERROR, "Unable to get %s", key); -                        goto out; -                } - -                ret = glusterd_op_perform_remove_brick (volinfo, brick); -                if (ret) -                        goto out; -                i++; -        } - -        ret = glusterd_create_volfiles_and_notify_services (volinfo); -        if (ret) -                goto out; - -        volinfo->defrag_status = 0; - -        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); - -        if (ret) -                goto out; - -        if (GLUSTERD_STATUS_STARTED == volinfo->status) -                ret = glusterd_check_generate_start_nfs (); - -out: -        return ret; -} - - -static int -glusterd_op_delete_volume (dict_t *dict) -{ -        int                                     ret = 0; -        char                                    *volname = NULL; -        glusterd_conf_t                         *priv = NULL; -        glusterd_volinfo_t                      *volinfo = NULL; -        xlator_t                                *this = NULL; - -        this = THIS; -        GF_ASSERT (this); -        priv = this->private; -        GF_ASSERT (priv); - -        ret = dict_get_str (dict, "volname", &volname); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        ret  = glusterd_volinfo_find (volname, &volinfo); - -        if (ret) -                goto out; - -        ret = glusterd_delete_volume (volinfo); -out: -        gf_log ("", GF_LOG_DEBUG, "returning %d", ret); -        return ret; -} - -static int -glusterd_op_start_volume (dict_t *dict, char **op_errstr) -{ -        int                                     ret = 0; -        char                                    *volname = NULL; -        int                                     flags = 0; -        glusterd_volinfo_t                      *volinfo = NULL; -        glusterd_brickinfo_t                    *brickinfo = NULL; - -        ret = glusterd_op_start_volume_args_get (dict, &volname, &flags); -        if (ret) -                goto out; - -        ret  = glusterd_volinfo_find (volname, &volinfo); - -        if (ret) -                goto out; -        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { -                ret = glusterd_brick_start (volinfo, brickinfo); -                if (ret) -                        goto out; -        } - -        glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STARTED); - -        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); -        if (ret) -                goto out; - -        ret = glusterd_check_generate_start_nfs (); - -out: -        gf_log ("", GF_LOG_DEBUG, "returning %d ", ret); -        return ret; -} - -static int -glusterd_op_log_filename (dict_t *dict) -{ -        int                   ret                = -1; -        glusterd_conf_t      *priv               = NULL; -        glusterd_volinfo_t   *volinfo            = NULL; -        glusterd_brickinfo_t *brickinfo          = NULL; -        xlator_t             *this               = NULL; -        char                 *volname            = NULL; -        char                 *brick              = NULL; -        char                 *path               = NULL; -        char                  logfile[PATH_MAX]  = {0,}; -        char                  exp_path[PATH_MAX] = {0,}; -        struct stat           stbuf              = {0,}; -        int                   valid_brick        = 0; -        glusterd_brickinfo_t *tmpbrkinfo         = NULL; -        char*                new_logdir         = NULL; - -        this = THIS; -        GF_ASSERT (this); -        priv = this->private; -        GF_ASSERT (priv); - -        ret = dict_get_str (dict, "volname", &volname); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "volname not found"); -                goto out; -        } - -        ret = dict_get_str (dict, "path", &path); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "path not found"); -                goto out; -        } - -        ret = dict_get_str (dict, "brick", &brick); -        if (ret) -                goto out; - -        ret  = glusterd_volinfo_find (volname, &volinfo); -        if (ret) -                goto out; - -        if (!strchr (brick, ':')) { -                brick = NULL; -                ret = stat (path, &stbuf); -                if (ret || !S_ISDIR (stbuf.st_mode)) { -                        ret = -1; -                        gf_log ("", GF_LOG_ERROR, "not a directory"); -                        goto out; -                } -                new_logdir = gf_strdup (path); -                if (!new_logdir) { -                        ret = -1; -                        gf_log ("", GF_LOG_ERROR, "Out of memory"); -                        goto out; -                } -                if (volinfo->logdir) -                        GF_FREE (volinfo->logdir); -                volinfo->logdir = new_logdir; -        } else { -                ret = glusterd_brickinfo_from_brick (brick, &tmpbrkinfo); -                if (ret) { -                        gf_log ("glusterd", GF_LOG_ERROR, -                                "cannot get brickinfo from brick"); -                        goto out; -                } -        } - - -        ret = -1; -        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - -                if (uuid_is_null (brickinfo->uuid)) { -                        ret = glusterd_resolve_brick (brickinfo); -                        if (ret) -                                goto out; -                } - -                /* check if the brickinfo belongs to the 'this' machine */ -                if (uuid_compare (brickinfo->uuid, priv->uuid)) -                        continue; - -                if (brick && strcmp (tmpbrkinfo->path,brickinfo->path)) -                        continue; - -                valid_brick = 1; - -                /* If there are more than one brick in 'this' server, its an -                 * extra check, but it doesn't harm functionality -                 */ -                ret = stat (path, &stbuf); -                if (ret || !S_ISDIR (stbuf.st_mode)) { -                        ret = -1; -                        gf_log ("", GF_LOG_ERROR, "not a directory"); -                        goto out; -                } - -                GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, exp_path); - -                snprintf (logfile, PATH_MAX, "%s/%s.log", path, exp_path); - -                if (brickinfo->logfile) -                        GF_FREE (brickinfo->logfile); -                brickinfo->logfile = gf_strdup (logfile); -                ret = 0; - -                /* If request was for brick, only one iteration is enough */ -                if (brick) -                        break; -        } - -        if (ret && !valid_brick) -                ret = 0; -out: -        if (tmpbrkinfo) -                glusterd_brickinfo_delete (tmpbrkinfo); - -        return ret; -} - -static int -glusterd_op_log_rotate (dict_t *dict) -{ -        int                   ret                = -1; -        glusterd_conf_t      *priv               = NULL; -        glusterd_volinfo_t   *volinfo            = NULL; -        glusterd_brickinfo_t *brickinfo          = NULL; -        xlator_t             *this               = NULL; -        char                 *volname            = NULL; -        char                 *brick              = NULL; -        char                  path[PATH_MAX]     = {0,}; -        char                  logfile[PATH_MAX]  = {0,}; -        char                  pidfile[PATH_MAX]  = {0,}; -        FILE                 *file               = NULL; -        pid_t                 pid                = 0; -        uint64_t              key                = 0; -        int                   valid_brick        = 0; -        glusterd_brickinfo_t *tmpbrkinfo         = NULL; - -        this = THIS; -        GF_ASSERT (this); -        priv = this->private; -        GF_ASSERT (priv); - -        ret = dict_get_str (dict, "volname", &volname); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "volname not found"); -                goto out; -        } - -        ret = dict_get_uint64 (dict, "rotate-key", &key); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "rotate key not found"); -                goto out; -        } - -        ret = dict_get_str (dict, "brick", &brick); -        if (ret) -                goto out; - -        if (!strchr (brick, ':')) -                brick = NULL; -        else { -                ret = glusterd_brickinfo_from_brick (brick, &tmpbrkinfo); -                if (ret) { -                        gf_log ("glusterd", GF_LOG_ERROR, -                                "cannot get brickinfo from brick"); -                        goto out; -                } -        } - -        ret = glusterd_volinfo_find (volname, &volinfo); -        if (ret) -                goto out; - -        ret = -1; -        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { -                if (uuid_compare (brickinfo->uuid, priv->uuid)) -                        continue; - -                if (brick && -                    (strcmp (tmpbrkinfo->hostname, brickinfo->hostname) || -                     strcmp (tmpbrkinfo->path,brickinfo->path))) -                        continue; - -                valid_brick = 1; - -                GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); -                GLUSTERD_GET_BRICK_PIDFILE (pidfile, path, brickinfo->hostname, -                                            brickinfo->path); - -                file = fopen (pidfile, "r+"); -                if (!file) { -                        gf_log ("", GF_LOG_ERROR, "Unable to open pidfile: %s", -                                pidfile); -                        ret = -1; -                        goto out; -                } - -                ret = fscanf (file, "%d", &pid); -                if (ret <= 0) { -                        gf_log ("", GF_LOG_ERROR, "Unable to read pidfile: %s", -                                pidfile); -                        ret = -1; -                        goto out; -                } -                fclose (file); -                file = NULL; - -                snprintf (logfile, PATH_MAX, "%s.%"PRIu64, -                          brickinfo->logfile, key); - -                ret = rename (brickinfo->logfile, logfile); -                if (ret) -                        gf_log ("", GF_LOG_WARNING, "rename failed"); - -                ret = kill (pid, SIGHUP); -                if (ret) { -                        gf_log ("", GF_LOG_ERROR, "Unable to SIGHUP to %d", pid); -                        goto out; -                } -                ret = 0; - -                /* If request was for brick, only one iteration is enough */ -                if (brick) -                        break; -        } - -        if (ret && !valid_brick) -                ret = 0; - -out: -        if (tmpbrkinfo) -                glusterd_brickinfo_delete (tmpbrkinfo); - -        return ret; -} - - -static int -glusterd_op_stop_volume (dict_t *dict) -{ -        int                                     ret = 0; -        int                                     flags = 0; -        char                                    *volname = NULL; -        glusterd_volinfo_t                      *volinfo = NULL; -        glusterd_brickinfo_t                    *brickinfo = NULL; - -        ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags); -        if (ret) -                goto out; - -        ret  = glusterd_volinfo_find (volname, &volinfo); - -        if (ret) -                goto out; - -        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { -                ret = glusterd_brick_stop (volinfo, brickinfo); -                if (ret) -                        goto out; -        } - -        glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STOPPED); - -        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); -        if (ret) -                goto out; - -        if (glusterd_are_all_volumes_stopped ()) { -                if (glusterd_is_nfs_started ()) { -                        ret = glusterd_nfs_server_stop (); -                        if (ret) -                                goto out; -                } -        } else { -                ret = glusterd_check_generate_start_nfs (); -        } - -out: -        return ret; -}  static int  glusterd_op_sync_volume (dict_t *dict, char **op_errstr, @@ -7289,145 +1918,6 @@ glusterd_op_brick_disconnect (void *data)          glusterd_op_sm ();  } -void -glusterd_do_replace_brick (void *data) -{ -        glusterd_volinfo_t     *volinfo = NULL; -        int32_t                 op      = 0; -        int32_t                 src_port = 0; -        int32_t                 dst_port = 0; -        dict_t                 *dict    = NULL; -        char                   *src_brick = NULL; -        char                   *dst_brick = NULL; -        char                   *volname   = NULL; -        glusterd_brickinfo_t   *src_brickinfo = NULL; -        glusterd_brickinfo_t   *dst_brickinfo = NULL; -	glusterd_conf_t	       *priv = NULL; - -        int ret = 0; - -        dict = data; - -	GF_ASSERT (THIS); - -	priv = THIS->private; - -	if (priv->timer) { -		gf_timer_call_cancel (THIS->ctx, priv->timer); -		priv->timer = NULL; -                gf_log ("", GF_LOG_DEBUG, -                        "Cancelled timer thread"); -	} - -        gf_log ("", GF_LOG_DEBUG, -                "Replace brick operation detected"); - -        ret = dict_get_int32 (dict, "operation", &op); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, -                        "dict_get on operation failed"); -                goto out; -        } -        ret = dict_get_str (dict, "src-brick", &src_brick); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); -                goto out; -        } - -        gf_log ("", GF_LOG_DEBUG, -                "src brick=%s", src_brick); - -        ret = dict_get_str (dict, "dst-brick", &dst_brick); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get dst brick"); -                goto out; -        } - -        gf_log ("", GF_LOG_DEBUG, -                "dst brick=%s", dst_brick); - -        ret = dict_get_str (dict, "volname", &volname); - -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        ret = glusterd_volinfo_find (volname, &volinfo); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); -                goto out; -        } - -        ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, &src_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, "Unable to get src-brickinfo"); -                goto out; -        } - -        ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); -        if (!dst_brickinfo) { -                gf_log ("", GF_LOG_DEBUG, "Unable to get dst-brickinfo"); -                goto out; -        } - -        ret = glusterd_resolve_brick (dst_brickinfo); -        if (ret) { -                gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); -                goto out; -        } - -        ret = dict_get_int32 (dict, "src-brick-port", &src_port); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get src-brick port"); -                goto out; -        } - -        ret = dict_get_int32 (dict, "dst-brick-port", &dst_port); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get dst-brick port"); -        } - -        dst_brickinfo->port = dst_port; -        src_brickinfo->port = src_port; - -        switch (op) { -        case GF_REPLACE_OP_START: -                if (!dst_port) { -                        ret = -1; -                        goto out; -                } - -                ret = rb_do_operation_start (volinfo, src_brickinfo, dst_brickinfo); -                if (ret) { -                        glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); -                        goto out; -                } -                break; -        case GF_REPLACE_OP_PAUSE: -        case GF_REPLACE_OP_ABORT: -        case GF_REPLACE_OP_COMMIT: -        case GF_REPLACE_OP_COMMIT_FORCE: -        case GF_REPLACE_OP_STATUS: -                break; -        default: -                ret = -1; -                goto out; -        } - -out: -        if (ret) -                ret = glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, NULL); -        else -                ret = glusterd_op_sm_inject_event (GD_OP_EVENT_COMMIT_ACC, NULL); - -        if (dict) -                dict_unref (dict); - -        glusterd_op_sm (); -} - -  static int  glusterd_op_ac_rcvd_commit_op_acc (glusterd_op_sm_event_t *event, void *ctx) @@ -7599,38 +2089,6 @@ glusterd_op_ac_unlocked_all (glusterd_op_sm_event_t *event, void *ctx)  }  static int -glusterd_op_stage_quota (dict_t *dict, char **op_errstr) -{ -        int                ret           = 0; -        char              *volname       = NULL; -        gf_boolean_t       exists        = _gf_false; - -        GF_ASSERT (dict); -        GF_ASSERT (op_errstr); - -        ret = dict_get_str (dict, "volname", &volname); -        if (ret) { -                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); -                goto out; -        } - -        exists = glusterd_check_volume_exists (volname); -        if (!exists) { -                gf_log ("", GF_LOG_ERROR, "Volume with name: %s " -                                "does not exist", -                                volname); -                *op_errstr = gf_strdup ("Invalid volume name"); -                ret = -1; -                goto out; -        } - -out: -        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); - -        return ret; -} - -static int  glusterd_op_ac_stage_op (glusterd_op_sm_event_t *event, void *ctx)  {          int                     ret = -1; diff --git a/xlators/mgmt/glusterd/src/glusterd-quota.c b/xlators/mgmt/glusterd/src/glusterd-quota.c new file mode 100644 index 000000000..809b56efe --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-quota.c @@ -0,0 +1,810 @@ +/* +  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/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "cli1.h" +#include "glusterd.h" +#include "glusterd-op-sm.h" +#include "glusterd-store.h" +#include "glusterd-utils.h" +#include "glusterd-volgen.h" +#include "run.h" + +#include <sys/wait.h> + +int +glusterd_handle_quota (rpcsvc_request_t *req) +{ +        int32_t                         ret = -1; +        gf1_cli_quota_req               cli_req = {0,}; +        dict_t                         *dict = NULL; +        glusterd_op_t                   cli_op = GD_OP_QUOTA; +        char                            operation[256] = {0, }; +        char                           *volname = NULL; +        int32_t                         type = 0; + +        GF_ASSERT (req); + +        if (!gf_xdr_to_cli_quota_req (req->msg[0], &cli_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        if (cli_req.dict.dict_len) { +                /* Unserialize the dictionary */ +                dict  = dict_new (); + +                ret = dict_unserialize (cli_req.dict.dict_val, +                                        cli_req.dict.dict_len, +                                        &dict); +                if (ret < 0) { +                        gf_log ("glusterd", GF_LOG_ERROR, "failed to " +                                    "unserialize req-buffer to dictionary"); +                        goto out; +                } else { +                        dict->extra_stdfree = cli_req.dict.dict_val; +                } +        } + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                gf_log ("", GF_LOG_WARNING, "Unable to get volume name, while" +                        "handling quota command"); +                goto out; +        } + +        ret = dict_get_int32 (dict, "type", &type); +        if (ret) { +                gf_log ("", GF_LOG_WARNING, "Unable to get type of cmd. , while" +                        "handling quota command"); +                goto out; +        } + +        switch (type) { +        case GF_QUOTA_OPTION_TYPE_ENABLE: +                strncpy (operation, "enable", sizeof (operation)); +                break; + +        case GF_QUOTA_OPTION_TYPE_DISABLE: +                strncpy (operation, "disable", sizeof (operation)); +                break; + +        case GF_QUOTA_OPTION_TYPE_LIMIT_USAGE: +                strncpy (operation, "limit-usage", sizeof (operation)); +                break; + +        case GF_QUOTA_OPTION_TYPE_REMOVE: +                strncpy (operation, "remove", sizeof (operation)); +                break; +        } +        gf_cmd_log ("volume quota", " %s command on %s", operation, volname); +        ret = glusterd_op_begin (req, GD_OP_QUOTA, dict); +        gf_cmd_log ("volume quota", " %s command on %s %s", operation,volname, +                    (ret != 0)? "FAILED" : "SUCCEEDED"); + +out: +        glusterd_friend_sm (); +        glusterd_op_sm (); + +        if (ret) { +                if (dict) +                        dict_unref (dict); +                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, +                                                     NULL, "operation failed"); +        } +        if (cli_req.volname) +                free (cli_req.volname); //malloced by xdr + +        return ret; +} + +int32_t +glusterd_check_if_quota_trans_enabled (glusterd_volinfo_t *volinfo) +{ +        int32_t  ret           = 0; +        int      flag          = _gf_false; + +        flag = glusterd_volinfo_get_boolean (volinfo, VKEY_FEATURES_QUOTA); +        if (flag == -1) { +                gf_log ("", GF_LOG_ERROR, "failed to get the quota status"); +                ret = -1; +                goto out; +        } + +        if (flag == _gf_false) { +                gf_log ("", GF_LOG_ERROR, "first enable the quota translator"); +                ret = -1; +                goto out; +        } +        ret = 0; +out: +        return ret; +} + +/* At the end of the function, the variable found will be set + * to true if the path to be removed was present in the limit-list, + * else will be false. + */ +int32_t +_glusterd_quota_remove_limits (char **quota_limits, char *path, +                               gf_boolean_t *found) +{ +        int      ret      = 0; +        int      i        = 0; +        int      size     = 0; +        int      len      = 0; +        int      pathlen  = 0; +        int      skiplen  = 0; +        int      flag     = 0; +        char    *limits   = NULL; +        char    *qlimits  = NULL; + +        if (found != NULL) +                *found = _gf_false; + +        if (*quota_limits == NULL) +                return -1; + +        qlimits = *quota_limits; + +        pathlen = strlen (path); + +        len = strlen (qlimits); + +        limits = GF_CALLOC (len + 1, sizeof (char), gf_gld_mt_char); +        if (!limits) +                return -1; + +        while (i < len) { +                if (!memcmp ((void *) &qlimits [i], (void *)path, pathlen)) +                        if (qlimits [i + pathlen] == ':') { +                                flag = 1; +                                if (found != NULL) +                                        *found = _gf_true; +                        } + +                while (qlimits [i + size] != ',' && +                       qlimits [i + size] != '\0') +                        size++; + +                if (!flag) { +                        memcpy ((void *) &limits [i], (void *) &qlimits [i], size + 1); +                } else { +                        skiplen = size + 1; +                        size = len - i - size; +                        memcpy ((void *) &limits [i], (void *) &qlimits [i + skiplen], size); +                        break; +                } + +                i += size + 1; +                size = 0; +        } + +        if (!flag) { +                ret = 1; +        } else { +                len = strlen (limits); + +                if (len == 0) { +                        GF_FREE (qlimits); + +                        *quota_limits = NULL; + +                        goto out; +                } + +                if (limits[len - 1] == ',') { +                        limits[len - 1] = '\0'; +                        len --; +                } + +                GF_FREE (qlimits); + +                qlimits = GF_CALLOC (len + 1, sizeof (char), gf_gld_mt_char); + +                if (!qlimits) { +                        ret = -1; +                        goto out; +                } + +                memcpy ((void *) qlimits, (void *) limits, len + 1); + +                *quota_limits = qlimits; + +                ret = 0; +        } + +out: +        if (limits) +                GF_FREE (limits); + +        return ret; +} + +int32_t +glusterd_quota_initiate_fs_crawl (glusterd_conf_t *priv, char *volname) +{ +        int32_t   ret = 0; +        pid_t     pid; +        char      mountdir [] = "/tmp/mntXXXXXX"; +        runner_t  runner = {0,}; +        int       status = 0; + +        if (mkdtemp (mountdir) == NULL) { +                gf_log ("glusterd", GF_LOG_DEBUG, +                        "failed to create a temporary mount directory"); +                ret = -1; +                goto out; +        } + +        runinit (&runner); +        runner_add_args (&runner, GFS_PREFIX"/sbin/glusterfs", "-s", +                         "localhost", "--volfile-id", volname, "-l", +                         DEFAULT_LOG_FILE_DIRECTORY"/quota-crawl.log", +                         mountdir, NULL); + +        ret = runner_run_reuse (&runner); +        if (ret == -1) { +                runner_log (&runner, "glusterd", GF_LOG_DEBUG, "command failed"); +                runner_end (&runner); +                goto out; +        } +        runner_end (&runner); + +        if ((pid = fork ()) < 0) { +                gf_log ("glusterd", GF_LOG_WARNING, "fork from parent failed"); +                ret = -1; +                goto out; +        } else if (pid == 0) {//first child +                /* fork one more to not hold back main process on +                 * blocking call below +                 */ +                pid = fork (); +                if (pid) +                        _exit (pid > 0 ? EXIT_SUCCESS : EXIT_FAILURE); + +                ret = chdir (mountdir); +                if (ret == -1) { +                        gf_log ("glusterd", GF_LOG_WARNING, "chdir %s failed, " +                                "reason: %s", mountdir, strerror (errno)); +                        exit (EXIT_FAILURE); +                } +                runinit (&runner); +                runner_add_args (&runner, "/usr/bin/find", "find", ".", NULL); +                if (runner_start (&runner) == -1) +                        _exit (EXIT_FAILURE); + +#ifndef GF_LINUX_HOST_OS +                runner_end (&runner); /* blocks in waitpid */ +                runcmd ("umount", mountdir, NULL); +#else +                runcmd ("umount", "-l", mountdir, NULL); +#endif +                rmdir (mountdir); +                _exit (EXIT_SUCCESS); +        } +        ret = (waitpid (pid, &status, 0) == pid && +               WIFEXITED (status) && WEXITSTATUS (status) == EXIT_SUCCESS) ? 0 : -1; + +out: +        return ret; +} + +char * +glusterd_quota_get_limit_value (char *quota_limits, char *path) +{ +        int32_t i, j, k, l, len; +        int32_t pat_len, diff; +        char   *ret_str = NULL; + +        len = strlen (quota_limits); +        pat_len = strlen (path); +        i = 0; +        j = 0; + +        while (i < len) { +                j = i; +                k = 0; +                while (path [k] == quota_limits [j]) { +                        j++; +                        k++; +                } + +                l = j; + +                while (quota_limits [j] != ',' && +                       quota_limits [j] != '\0') +                        j++; + +                if (quota_limits [l] == ':' && pat_len == (l - i)) { +                        diff = j - i; +                        ret_str = GF_CALLOC (diff + 1, sizeof (char), +                                             gf_gld_mt_char); + +                        strncpy (ret_str, "a_limits [i], diff); + +                        break; +                } +                i = ++j; //skip ',' +        } + +        return ret_str; +} + +char* +_glusterd_quota_get_limit_usages (glusterd_volinfo_t *volinfo, +                                  char *path, char **op_errstr) +{ +        int32_t  ret          = 0; +        char    *quota_limits = NULL; +        char    *ret_str      = NULL; + +        if (volinfo == NULL) +                return NULL; + +        ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, +                                    "a_limits); +        if (ret) +                return NULL; +        if (quota_limits == NULL) { +                ret_str = NULL; +                *op_errstr = gf_strdup ("Limit not set on any directory"); +        } else if (path == NULL) +                ret_str = gf_strdup (quota_limits); +        else +                ret_str = glusterd_quota_get_limit_value (quota_limits, path); + +        return ret_str; +} + +int32_t +glusterd_quota_get_limit_usages (glusterd_conf_t *priv, +                                 glusterd_volinfo_t *volinfo, +                                 char *volname, +                                 dict_t *dict, +                                 char **op_errstr) +{ +        int32_t i               = 0; +        int32_t ret             = 0; +        int32_t count           = 0; +        char    *path           = NULL; +        dict_t  *ctx            = NULL; +        char    cmd_str [1024]  = {0, }; +        char   *ret_str         = NULL; + +        ctx = glusterd_op_get_ctx (); +        if (ctx == NULL) +                return 0; + +        ret = dict_get_int32 (dict, "count", &count); +        if (ret < 0) +                goto out; + +        if (count == 0) { +                ret_str = _glusterd_quota_get_limit_usages (volinfo, NULL, +                                                            op_errstr); +        } else { +                i = 0; +                while (count--) { +                        snprintf (cmd_str, 1024, "path%d", i++); + +                        ret = dict_get_str (dict, cmd_str, &path); +                        if (ret < 0) +                                goto out; + +                        ret_str = _glusterd_quota_get_limit_usages (volinfo, path, op_errstr); +                } +        } + +        if (ret_str) { +                ret = dict_set_dynstr (ctx, "limit_list", ret_str); +        } +out: +        return ret; +} + +int32_t +glusterd_quota_enable (glusterd_volinfo_t *volinfo, char **op_errstr, +                       gf_boolean_t *crawl) +{ +        int32_t         ret     = -1; +        char            *quota_status = NULL; + +        GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); +        GF_VALIDATE_OR_GOTO ("glusterd", crawl, out); +        GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); + +        if (glusterd_is_volume_started (volinfo) == 0) { +                *op_errstr = gf_strdup ("Volume is stopped, start volume " +                                        "to enable quota."); +                goto out; +        } + +        ret = glusterd_check_if_quota_trans_enabled (volinfo); +        if (ret == 0) { +                *op_errstr = gf_strdup ("Quota is already enabled"); +                goto out; +        } + +        quota_status = gf_strdup ("on"); +        if (!quota_status) { +                gf_log ("", GF_LOG_ERROR, "memory allocation failed"); +                *op_errstr = gf_strdup ("Enabling quota has been unsuccessful"); +                goto out; +        } + +        ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, quota_status); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "dict set failed"); +                *op_errstr = gf_strdup ("Enabling quota has been unsuccessful"); +                goto out; +        } + +        *op_errstr = gf_strdup ("Enabling quota has been successful"); + +        *crawl = _gf_true; + +        ret = 0; +out: +        return ret; +} + +int32_t +glusterd_quota_disable (glusterd_volinfo_t *volinfo, char **op_errstr) +{ +        int32_t  ret            = -1; +        char    *quota_status   = NULL, *quota_limits = NULL; + +        GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); +        GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); + +        ret = glusterd_check_if_quota_trans_enabled (volinfo); +        if (ret == -1) { +                *op_errstr = gf_strdup ("Quota is already disabled"); +                goto out; +        } + +        quota_status = gf_strdup ("off"); +        if (!quota_status) { +                gf_log ("", GF_LOG_ERROR, "memory allocation failed"); +                *op_errstr = gf_strdup ("Disabling quota has been unsuccessful"); +                goto out; +        } + +        ret = dict_set_dynstr (volinfo->dict, VKEY_FEATURES_QUOTA, quota_status); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "dict set failed"); +                *op_errstr = gf_strdup ("Disabling quota has been unsuccessful"); +                goto out; +        } + +        *op_errstr = gf_strdup ("Disabling quota has been successful"); + +        ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, +                                    "a_limits); +        if (ret) { +                gf_log ("", GF_LOG_WARNING, "failed to get the quota limits"); +        } else { +                GF_FREE (quota_limits); +        } + +        dict_del (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE); + +out: +        return ret; +} + +int32_t +glusterd_quota_limit_usage (glusterd_volinfo_t *volinfo, dict_t *dict, char **op_errstr) +{ +        int32_t          ret    = -1; +        char            *path   = NULL; +        char            *limit  = NULL; +        char            *value  = NULL; +        char             msg [1024] = {0,}; +        char            *quota_limits = NULL; + +        GF_VALIDATE_OR_GOTO ("glusterd", dict, out); +        GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); +        GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); + +        ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, +                                    "a_limits); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "failed to get the quota limits"); +                *op_errstr = gf_strdup ("failed to set limit"); +                goto out; +        } + +        ret = dict_get_str (dict, "path", &path); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); +                *op_errstr = gf_strdup ("failed to set limit"); +                goto out; +        } + +        ret = dict_get_str (dict, "limit", &limit); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); +                *op_errstr = gf_strdup ("failed to set limit"); +                goto out; +        } + +        if (quota_limits) { +                ret = _glusterd_quota_remove_limits ("a_limits, path, NULL); +                if (ret == -1) { +                        gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); +                        *op_errstr = gf_strdup ("failed to set limit"); +                        goto out; +                } +        } + +        if (quota_limits == NULL) { +                ret = gf_asprintf (&value, "%s:%s", path, limit); +                if (ret == -1) { +                        gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); +                        *op_errstr = gf_strdup ("failed to set limit"); +                        goto out; +                } +        } else { +                ret = gf_asprintf (&value, "%s,%s:%s", +                                   quota_limits, path, limit); +                if (ret == -1) { +                        gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); +                        *op_errstr = gf_strdup ("failed to set limit"); +                        goto out; +                } + +                GF_FREE (quota_limits); +        } + +        quota_limits = value; + +        ret = dict_set_str (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE, +                            quota_limits); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to set quota limits" ); +                *op_errstr = gf_strdup ("failed to set limit"); +                goto out; +        } +        snprintf (msg, 1024, "limit set on %s", path); +        *op_errstr = gf_strdup (msg); + +        ret = 0; +out: +        return ret; +} + +int32_t +glusterd_quota_remove_limits (glusterd_volinfo_t *volinfo, dict_t *dict, char **op_errstr) +{ +        int32_t         ret                   = -1; +        char            str [PATH_MAX + 1024] = {0,}; +        char            *quota_limits         = NULL; +        char            *path                 = NULL; +        gf_boolean_t     flag                 = _gf_false; + +        GF_VALIDATE_OR_GOTO ("glusterd", dict, out); +        GF_VALIDATE_OR_GOTO ("glusterd", volinfo, out); +        GF_VALIDATE_OR_GOTO ("glusterd", op_errstr, out); + +        ret = glusterd_check_if_quota_trans_enabled (volinfo); +        if (ret == -1) { +                *op_errstr = gf_strdup ("Quota is disabled, please enable quota"); +                goto out; +        } + +        ret = glusterd_volinfo_get (volinfo, VKEY_FEATURES_LIMIT_USAGE, +                                    "a_limits); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "failed to get the quota limits"); +                goto out; +        } + +        ret = dict_get_str (dict, "path", &path); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to fetch quota limits" ); +                goto out; +        } + +        ret = _glusterd_quota_remove_limits ("a_limits, path, &flag); +        if (ret == -1) { +                if (flag == _gf_true) +                        snprintf (str, sizeof (str), "Removing limit on %s has " +                                  "been unsuccessful", path); +                else +                        snprintf (str, sizeof (str), "%s has no limit set", path); +                *op_errstr = gf_strdup (str); +                goto out; +        } else { +                if (flag == _gf_true) +                        snprintf (str, sizeof (str), "Removed quota limit on " +                                  "%s", path); +                else +                        snprintf (str, sizeof (str), "no limit set on %s", +                                  path); +                *op_errstr = gf_strdup (str); +        } + +        if (quota_limits) { +                ret = dict_set_str (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE, +                                    quota_limits); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, "Unable to set quota limits" ); +                        goto out; +                } +        } else { +               dict_del (volinfo->dict, VKEY_FEATURES_LIMIT_USAGE); +        } + +        ret = 0; + +out: +        return ret; +} + + +int +glusterd_op_quota (dict_t *dict, char **op_errstr) +{ +        glusterd_volinfo_t     *volinfo      = NULL; +        int32_t                 ret          = -1; +        char                   *volname      = NULL; +        dict_t                 *ctx          = NULL; +        int                     type         = -1; +        gf_boolean_t            start_crawl  = _gf_false; +        glusterd_conf_t        *priv         = NULL; + +        GF_ASSERT (dict); +        GF_ASSERT (op_errstr); + +        priv = THIS->private; + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name " ); +                goto out; +        } + +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); +                goto out; +        } + +        ret = dict_get_int32 (dict, "type", &type); + +        if (type == GF_QUOTA_OPTION_TYPE_ENABLE) { +                ret = glusterd_quota_enable (volinfo, op_errstr, &start_crawl); +                if (ret < 0) +                        goto out; + +                goto create_vol; +        } + +        if (type == GF_QUOTA_OPTION_TYPE_DISABLE) { +                ret = glusterd_quota_disable (volinfo, op_errstr); +                if (ret < 0) +                        goto out; + +                goto create_vol; +        } + +        if (type == GF_QUOTA_OPTION_TYPE_LIMIT_USAGE) { +                ret = glusterd_quota_limit_usage (volinfo, dict, op_errstr); +                if (ret < 0) +                        goto out; + +                goto create_vol; +        } + +        if (type == GF_QUOTA_OPTION_TYPE_REMOVE) { +                ret = glusterd_quota_remove_limits (volinfo, dict, op_errstr); +                if (ret < 0) +                        goto out; + +                goto create_vol; +        } + +        if (type == GF_QUOTA_OPTION_TYPE_LIST) { +                ret = glusterd_check_if_quota_trans_enabled (volinfo); +                if (ret == -1) { +                        *op_errstr = gf_strdup ("cannot list the limits, " +                                                "quota is disabled"); +                        goto out; +                } + +                ret = glusterd_quota_get_limit_usages (priv, volinfo, volname, +                                                       dict, op_errstr); + +                goto out; +        } +create_vol: +        ret = glusterd_create_volfiles_and_notify_services (volinfo); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to re-create volfile for" +                                          " 'quota'"); +                ret = -1; +                goto out; +        } + +        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); +        if (ret) +                goto out; + +        if (GLUSTERD_STATUS_STARTED == volinfo->status) +                ret = glusterd_check_generate_start_nfs (); + +        ret = 0; + +out: +        ctx = glusterd_op_get_ctx (); +        if (ctx && start_crawl == _gf_true) +                glusterd_quota_initiate_fs_crawl (priv, volname); + +        if (ctx && *op_errstr) { +                ret = dict_set_dynstr (ctx, "errstr", *op_errstr); +                if (ret) { +                        GF_FREE (*op_errstr); +                        gf_log ("", GF_LOG_DEBUG, +                                "failed to set error message in ctx"); +                } +                *op_errstr = NULL; +        } + +        return ret; +} + +int +glusterd_op_stage_quota (dict_t *dict, char **op_errstr) +{ +        int                ret           = 0; +        char              *volname       = NULL; +        gf_boolean_t       exists        = _gf_false; + +        GF_ASSERT (dict); +        GF_ASSERT (op_errstr); + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        exists = glusterd_check_volume_exists (volname); +        if (!exists) { +                gf_log ("", GF_LOG_ERROR, "Volume with name: %s " +                                "does not exist", +                                volname); +                *op_errstr = gf_strdup ("Invalid volume name"); +                ret = -1; +                goto out; +        } + +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +        return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c new file mode 100644 index 000000000..16fd0bb82 --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c @@ -0,0 +1,1929 @@ +/* +  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/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "cli1.h" +#include "glusterd.h" +#include "glusterd-op-sm.h" +#include "glusterd-store.h" +#include "glusterd-utils.h" +#include "glusterd-volgen.h" +#include "run.h" +#include "syscall.h" + +#include <signal.h> + +int +glusterd_handle_replace_brick (rpcsvc_request_t *req) +{ +        int32_t                         ret = -1; +        gf1_cli_replace_brick_req          cli_req = {0,}; +        dict_t                          *dict = NULL; +        char                            *src_brick = NULL; +        char                            *dst_brick = NULL; +        int32_t                         op = 0; +        char                            operation[256]; +        glusterd_op_t                   cli_op = GD_OP_REPLACE_BRICK; + +        GF_ASSERT (req); + +        if (!gf_xdr_to_cli_replace_brick_req (req->msg[0], &cli_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        gf_log ("glusterd", GF_LOG_INFO, "Received replace brick req"); + +        if (cli_req.bricks.bricks_len) { +                /* Unserialize the dictionary */ +                dict  = dict_new (); + +                ret = dict_unserialize (cli_req.bricks.bricks_val, +                                        cli_req.bricks.bricks_len, +                                        &dict); +                if (ret < 0) { +                        gf_log ("glusterd", GF_LOG_ERROR, +                                "failed to " +                                "unserialize req-buffer to dictionary"); +                        goto out; +                } else { +                        dict->extra_stdfree = cli_req.bricks.bricks_val; +                } +        } + +        ret = dict_get_int32 (dict, "operation", &op); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "dict_get on operation failed"); +                goto out; +        } + +        ret = dict_get_str (dict, "src-brick", &src_brick); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); +                goto out; +        } +        gf_log ("", GF_LOG_DEBUG, +                "src brick=%s", src_brick); + +        ret = dict_get_str (dict, "dst-brick", &dst_brick); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get dest brick"); +                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",cli_req.volname, src_brick, dst_brick +                    ,operation); + +        ret = glusterd_op_begin (req, GD_OP_REPLACE_BRICK, dict); +        gf_cmd_log ("Volume replace-brick","on volname: %s %s", cli_req.volname, +                   (ret) ? "FAILED" : "SUCCESS"); + +out: +        if (ret && dict) +                dict_unref (dict); +        if (cli_req.volname) +                free (cli_req.volname);//malloced by xdr + +        glusterd_friend_sm (); +        glusterd_op_sm (); + +        if (ret) +                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, +                                                     NULL, "operation failed"); + +        return ret; +} + + +char * +glusterd_check_brick_rb_part (char *bricks, int count, glusterd_volinfo_t *volinfo) +{ +        char                                    *saveptr = NULL; +        char                                    *brick = NULL; +        char                                    *brick_list = NULL; +        int                                     ret = 0; +        glusterd_brickinfo_t                    *brickinfo = NULL; +        uint32_t                                i = 0; +        char                                    *str = NULL; +        char                                    msg[2048] = {0,}; + +        brick_list = gf_strdup (bricks); +        if (!brick_list) { +                gf_log ("glusterd", GF_LOG_ERROR, +                        "Out of memory"); +                ret = -1; +                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; +} + +static int +glusterd_get_rb_dst_brickinfo (glusterd_volinfo_t *volinfo, +                               glusterd_brickinfo_t **brickinfo) +{ +        int32_t                 ret = -1; + +        if (!volinfo || !brickinfo) +                goto out; + +        *brickinfo = volinfo->dst_brick; + +        ret = 0; + +out: +        return ret; +} + +int +glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, +                                 dict_t *rsp_dict) +{ +        int                                      ret           = 0; +        char                                    *src_brick     = NULL; +        char                                    *dst_brick     = NULL; +        char                                    *volname       = NULL; +        int                                      replace_op    = 0; +        glusterd_volinfo_t                      *volinfo       = NULL; +        glusterd_brickinfo_t                    *src_brickinfo = NULL; +        char                                    *host          = NULL; +        char                                    *path          = NULL; +        char                                    msg[2048]      = {0}; +        char                                    *dup_dstbrick  = NULL; +        glusterd_peerinfo_t                     *peerinfo = NULL; +        glusterd_brickinfo_t                    *dst_brickinfo = NULL; +        gf_boolean_t                            is_run         = _gf_false; + +        ret = dict_get_str (dict, "src-brick", &src_brick); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); +                goto out; +        } + +        gf_log ("", GF_LOG_DEBUG, "src brick=%s", src_brick); + +        ret = dict_get_str (dict, "dst-brick", &dst_brick); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get dest brick"); +                goto out; +        } + +        gf_log ("", GF_LOG_DEBUG, "dst brick=%s", dst_brick); + +        ret = dict_get_str (dict, "volname", &volname); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        ret = dict_get_int32 (dict, "operation", (int32_t *)&replace_op); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "dict get on replace-brick operation failed"); +                goto out; +        } + +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (ret) { +                snprintf (msg, sizeof (msg), "volume: %s does not exist", +                          volname); +                *op_errstr = gf_strdup (msg); +                goto out; +        } + +        if (GLUSTERD_STATUS_STARTED != volinfo->status) { +                ret = -1; +                snprintf (msg, sizeof (msg), "volume: %s is not started", +                          volname); +                *op_errstr = gf_strdup (msg); +                goto out; +        } + +        if (!glusterd_store_is_valid_brickpath (volname, dst_brick) || +                !glusterd_is_valid_volfpath (volname, dst_brick)) { +                snprintf (msg, sizeof (msg), "brick path %s is too " +                          "long.", dst_brick); +                gf_log ("", GF_LOG_ERROR, "%s", msg); +                *op_errstr = gf_strdup (msg); + +                ret = -1; +                goto out; +        } + +        ret = glusterd_check_gsync_running (volinfo, &is_run); +        if (ret && (is_run == _gf_false)) +                gf_log ("", GF_LOG_WARNING, "Unable to get the status" +                                " of active "GEOREP" session"); +        if (is_run) { +                gf_log ("", GF_LOG_WARNING, GEOREP" sessions active" +                        "for the volume %s ", volname); +                snprintf (msg, sizeof(msg), GEOREP" sessions are active " +                                "for the volume %s.\nStop "GEOREP "sessions " +                                "involved in this volume. Use 'volume "GEOREP +                                " status' command for more info.", +                                volname); +                *op_errstr = gf_strdup (msg); +                ret = -1; +                goto out; +        } + +        if (glusterd_is_defrag_on(volinfo)) { +                snprintf (msg, sizeof(msg), "Volume name %s rebalance is in " +                          "progress. Please retry after completion", volname); +                gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); +                *op_errstr = gf_strdup (msg); +                ret = -1; +                goto out; +        } + +        switch (replace_op) { +        case GF_REPLACE_OP_START: +                if (glusterd_is_rb_started (volinfo)) { +                        gf_log ("", GF_LOG_ERROR, "Replace brick is already " +                                "started for volume "); +                        ret = -1; +                        goto out; +                } +                break; +        case GF_REPLACE_OP_PAUSE: +                if (glusterd_is_rb_paused (volinfo)) { +                        gf_log ("", GF_LOG_ERROR, "Replace brick is already " +                                "paused for volume "); +                        ret = -1; +                        goto out; +                } else if (!glusterd_is_rb_started(volinfo)) { +                        gf_log ("", GF_LOG_ERROR, "Replace brick is not" +                                " started for volume "); +                        ret = -1; +                        goto out; +                } +                break; + +        case GF_REPLACE_OP_ABORT: +                if ((!glusterd_is_rb_paused (volinfo)) && +                     (!glusterd_is_rb_started (volinfo))) { +                        gf_log ("", GF_LOG_ERROR, "Replace brick is not" +                                " started or paused for volume "); +                        ret = -1; +                        goto out; +                } +                break; + +        case GF_REPLACE_OP_COMMIT: +                if (!glusterd_is_rb_started (volinfo)) { +                        gf_log ("", GF_LOG_ERROR, "Replace brick is not " +                                "started for volume "); +                        ret = -1; +                        goto out; +                } +                break; + +        case GF_REPLACE_OP_COMMIT_FORCE: break; +        case GF_REPLACE_OP_STATUS: +                break; +        default: +                ret = -1; +                goto out; +        } + +        ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, +                                                      &src_brickinfo); +        if (ret) { +                snprintf (msg, sizeof (msg), "brick: %s does not exist in " +                          "volume: %s", src_brick, volname); +                *op_errstr = gf_strdup (msg); +                goto out; +        } + +        if (!glusterd_is_local_addr (src_brickinfo->hostname)) { +                gf_log ("", GF_LOG_DEBUG, +                        "I AM THE SOURCE HOST"); +                if (src_brickinfo->port && rsp_dict) { +                        ret = dict_set_int32 (rsp_dict, "src-brick-port", +                                              src_brickinfo->port); +                        if (ret) { +                                gf_log ("", GF_LOG_DEBUG, +                                        "Could not set src-brick-port=%d", +                                        src_brickinfo->port); +                        } +                } + +        } + +        dup_dstbrick = gf_strdup (dst_brick); +        if (!dup_dstbrick) { +                ret = -1; +                gf_log ("", GF_LOG_ERROR, "Memory allocation failed"); +                goto out; +        } +        host = strtok (dup_dstbrick, ":"); +        path = strtok (NULL, ":"); + +        if (!host || !path) { +                gf_log ("", GF_LOG_ERROR, +                        "dst brick %s is not of form <HOSTNAME>:<export-dir>", +                        dst_brick); +                ret = -1; +                goto out; +        } +        if (!glusterd_brickinfo_get (NULL, host, path, NULL)) { +                snprintf(msg, sizeof(msg), "Brick: %s:%s already in use", +                         host, path); +                *op_errstr = gf_strdup (msg); +                ret = -1; +                goto out; +        } + +        if ((volinfo->rb_status ==GF_RB_STATUS_NONE) && +            (replace_op == GF_REPLACE_OP_START)) { +                ret = glusterd_brickinfo_from_brick (dst_brick, &dst_brickinfo); +                volinfo->src_brick = src_brickinfo; +                volinfo->dst_brick = dst_brickinfo; +        } else { +                ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); +        } + +        if (glusterd_rb_check_bricks (volinfo, src_brickinfo, dst_brickinfo)) { +                gf_log ("", GF_LOG_ERROR, "replace brick: incorrect source or" +                       "  destination bricks specified"); +                ret = -1; +                goto out; +       } +        if (!glusterd_is_local_addr (host)) { +                ret = glusterd_brick_create_path (host, path, +                                                  volinfo->volume_id, 0777, +                                                  op_errstr); +                if (ret) +                        goto out; +        } else { +                ret = glusterd_friend_find (NULL, host, &peerinfo); +                if (ret) { +                        snprintf (msg, sizeof (msg), "%s, is not a friend", +                                  host); +                        *op_errstr = gf_strdup (msg); +                        goto out; +                } + +                if (!peerinfo->connected) { +                        snprintf (msg, sizeof (msg), "%s, is not connected at " +                                  "the moment", host); +                        *op_errstr = gf_strdup (msg); +                        ret = -1; +                        goto out; +                } + +                if (GD_FRIEND_STATE_BEFRIENDED != peerinfo->state.state) { +                        snprintf (msg, sizeof (msg), "%s, is not befriended " +                                  "at the moment", host); +                        *op_errstr = gf_strdup (msg); +                        ret = -1; +                        goto out; +                } +        } +        ret = 0; + +out: +        if (dup_dstbrick) +                GF_FREE (dup_dstbrick); +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +        return ret; +} + +static int +rb_regenerate_volfiles (glusterd_volinfo_t *volinfo, +                        glusterd_brickinfo_t *brickinfo, +                        int32_t pump_needed) +{ +        dict_t *dict = NULL; +        int ret = 0; + +        dict = volinfo->dict; + +        gf_log ("", GF_LOG_DEBUG, +                "attempting to set pump value=%d", pump_needed); + +        ret = dict_set_int32 (dict, "enable-pump", pump_needed); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "could not dict_set enable-pump"); +                goto out; +        } + +        ret = glusterd_create_rb_volfiles (volinfo, brickinfo); + +out: +        return ret; +} + +static int +rb_src_brick_restart (glusterd_volinfo_t *volinfo, +                      glusterd_brickinfo_t *src_brickinfo, +                      int activate_pump) +{ +        int                     ret = 0; + +        gf_log ("", GF_LOG_DEBUG, +                "Attempting to kill src"); + +        ret = glusterd_nfs_server_stop (); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to stop nfs, ret: %d", +                        ret); +        } + +        ret = glusterd_volume_stop_glusterfs (volinfo, src_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to stop " +                        "glusterfs, ret: %d", ret); +                goto out; +        } + +        glusterd_delete_volfile (volinfo, src_brickinfo); + +        if (activate_pump) { +                ret = rb_regenerate_volfiles (volinfo, src_brickinfo, 1); +                if (ret) { +                        gf_log ("", GF_LOG_DEBUG, +                                "Could not regenerate volfiles with pump"); +                        goto out; +                } +        } else { +                ret = rb_regenerate_volfiles (volinfo, src_brickinfo, 0); +                if (ret) { +                        gf_log ("", GF_LOG_DEBUG, +                                "Could not regenerate volfiles without pump"); +                        goto out; +                } + +        } + +        sleep (2); +        ret = glusterd_volume_start_glusterfs (volinfo, src_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to start " +                        "glusterfs, ret: %d", ret); +                goto out; +        } + +out: +        ret = glusterd_nfs_server_start (); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to start nfs, ret: %d", +                        ret); +        } +        return ret; +} + +static int +rb_send_xattr_command (glusterd_volinfo_t *volinfo, +                       glusterd_brickinfo_t *src_brickinfo, +                       glusterd_brickinfo_t *dst_brickinfo, +                       const char *xattr_key, +                       const char *value) +{ +        glusterd_conf_t  *priv                        = NULL; +        char              mount_point_path[PATH_MAX]  = {0,}; +        struct stat       buf; +        int               ret                         = -1; + +        priv = THIS->private; + +        snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", +                  priv->workdir, volinfo->volname, +                  RB_CLIENT_MOUNTPOINT); + +        ret = stat (mount_point_path, &buf); +         if (ret) { +                 gf_log ("", GF_LOG_DEBUG, +                         "stat failed. Could not send " +                         " %s command", xattr_key); +                 goto out; +         } + +        ret = sys_lsetxattr (mount_point_path, xattr_key, +                         value, +                         strlen (value) + 1, +                         0); + +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "setxattr failed"); +                goto out; +        } + +        ret = 0; + +out: +        return ret; +} + +static int +rb_spawn_dst_brick (glusterd_volinfo_t *volinfo, +                    glusterd_brickinfo_t *brickinfo) +{ +        glusterd_conf_t    *priv           = NULL; +        runner_t            runner         = {0,}; +        int                 ret            = -1; +        int32_t             port           = 0; + +        priv = THIS->private; + +        port = pmap_registry_alloc (THIS); +        brickinfo->port = port; + +        GF_ASSERT (port); + +        runinit (&runner); +        runner_add_arg (&runner, GFS_PREFIX"/sbin/glusterfs"); +        runner_argprintf (&runner, "-f" "%s/vols/%s/"RB_DSTBRICKVOL_FILENAME, +                          priv->workdir, volinfo->volname); +        runner_argprintf (&runner, "-p" "%s/vols/%s/"RB_DSTBRICK_PIDFILE, +                          priv->workdir, volinfo->volname); +        runner_add_arg (&runner, "--xlator-option"); +        runner_argprintf (&runner, "src-server.listen-port=%d", port); + +        ret = runner_run (&runner); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "Could not start glusterfs"); +                goto out; +        } + +        gf_log ("", GF_LOG_DEBUG, +                "Successfully started glusterfs: brick=%s:%s", +                brickinfo->hostname, brickinfo->path); + +        ret = 0; + +out: +        return ret; +} + +static int +rb_spawn_glusterfs_client (glusterd_volinfo_t *volinfo, +                           glusterd_brickinfo_t *brickinfo) +{ +        glusterd_conf_t    *priv           = NULL; +        char                cmd_str[8192]  = {0,}; +        runner_t            runner         = {0,}; +        struct stat         buf; +        int                 ret            = -1; + +        priv = THIS->private; + +        runinit (&runner); +        runner_add_arg (&runner, GFS_PREFIX"/sbin/glusterfs"); +        runner_argprintf (&runner, "-f" "%s/vols/%s/"RB_CLIENTVOL_FILENAME, +                          priv->workdir, volinfo->volname); +        runner_argprintf (&runner, "%s/vols/%s/"RB_CLIENT_MOUNTPOINT, +                          priv->workdir, volinfo->volname); + +        ret = runner_run (&runner); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "Could not start glusterfs"); +                goto out; +        } + +        gf_log ("", GF_LOG_DEBUG, +                "Successfully started glusterfs: brick=%s:%s", +                brickinfo->hostname, brickinfo->path); + +        memset (cmd_str, 0, sizeof (cmd_str)); + +        snprintf (cmd_str, 4096, "%s/vols/%s/%s", +                  priv->workdir, volinfo->volname, +                  RB_CLIENT_MOUNTPOINT); + +        ret = stat (cmd_str, &buf); +        if (ret) { +                 gf_log ("", GF_LOG_DEBUG, +                         "stat on mountpoint failed"); +                 goto out; +         } + +         gf_log ("", GF_LOG_DEBUG, +                 "stat on mountpoint succeeded"); + +        ret = 0; + +out: +        return ret; +} + +static const char *client_volfile_str =  "volume mnt-client\n" +        " type protocol/client\n" +        " option remote-host %s\n" +        " option remote-subvolume %s\n" +        " option remote-port %d\n" +        " option transport-type %s\n" +        "end-volume\n" +        "volume mnt-wb\n" +        " type performance/write-behind\n" +        " subvolumes mnt-client\n" +        "end-volume\n"; + +static int +rb_generate_client_volfile (glusterd_volinfo_t *volinfo, +                            glusterd_brickinfo_t *src_brickinfo) +{ +        glusterd_conf_t  *priv                  = NULL; +        FILE             *file                  = NULL; +        char              filename[PATH_MAX]    = {0, }; +        int               ret                   = -1; +        char             *ttype                 = NULL; + +        priv = THIS->private; + +        gf_log ("", GF_LOG_DEBUG, +                "Creating volfile"); + +        snprintf (filename, PATH_MAX, "%s/vols/%s/%s", +                  priv->workdir, volinfo->volname, +                  RB_CLIENTVOL_FILENAME); + +        file = fopen (filename, "w+"); +        if (!file) { +                gf_log ("", GF_LOG_DEBUG, +                        "Open of volfile failed"); +                ret = -1; +                goto out; +        } + +        GF_ASSERT (src_brickinfo->port); + +	ttype = glusterd_get_trans_type_rb (volinfo->transport_type); +	if (NULL == ttype){ +		ret = -1; +		goto out; +	} + +        fprintf (file, client_volfile_str, src_brickinfo->hostname, +                 src_brickinfo->path, src_brickinfo->port, ttype); + +        fclose (file); +        GF_FREE (ttype); + +        ret = 0; + +out: +        return ret; +} + +static const char *dst_brick_volfile_str = "volume src-posix\n" +        " type storage/posix\n" +        " option directory %s\n" +        "end-volume\n" +        "volume %s\n" +        " type features/locks\n" +        " subvolumes src-posix\n" +        "end-volume\n" +        "volume src-server\n" +        " type protocol/server\n" +        " option auth.addr.%s.allow *\n" +        " option transport-type %s\n" +        " subvolumes %s\n" +        "end-volume\n"; + +static int +rb_generate_dst_brick_volfile (glusterd_volinfo_t *volinfo, +                               glusterd_brickinfo_t *dst_brickinfo) +{ +        glusterd_conf_t    *priv                = NULL; +        FILE               *file                = NULL; +        char                filename[PATH_MAX]  = {0, }; +        int                 ret                 = -1; +        char               *trans_type          = NULL; + +        priv = THIS->private; + +        gf_log ("", GF_LOG_DEBUG, +                "Creating volfile"); + +        snprintf (filename, PATH_MAX, "%s/vols/%s/%s", +                  priv->workdir, volinfo->volname, +                  RB_DSTBRICKVOL_FILENAME); + +        file = fopen (filename, "w+"); +        if (!file) { +                gf_log ("", GF_LOG_DEBUG, +                        "Open of volfile failed"); +                ret = -1; +                goto out; +        } + +	trans_type = glusterd_get_trans_type_rb (volinfo->transport_type); +	if (NULL == trans_type){ +		ret = -1; +		goto out; +	} + +        fprintf (file, dst_brick_volfile_str, dst_brickinfo->path, +                 dst_brickinfo->path, dst_brickinfo->path, +                 trans_type, dst_brickinfo->path); + +	GF_FREE (trans_type); + +        fclose (file); + +        ret = 0; + +out: +        return ret; +} + + +static int +rb_mountpoint_mkdir (glusterd_volinfo_t *volinfo, +                     glusterd_brickinfo_t *src_brickinfo) +{ +        glusterd_conf_t *priv                       = NULL; +        char             mount_point_path[PATH_MAX] = {0,}; +        int              ret                        = -1; + +        priv = THIS->private; + +        snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", +                  priv->workdir, volinfo->volname, +                  RB_CLIENT_MOUNTPOINT); + +        ret = mkdir (mount_point_path, 0777); +        if (ret && (errno != EEXIST)) { +                gf_log ("", GF_LOG_DEBUG, "mkdir failed, errno: %d", +                        errno); +                goto out; +        } + +        ret = 0; + +out: +        return ret; +} + +static int +rb_mountpoint_rmdir (glusterd_volinfo_t *volinfo, +                     glusterd_brickinfo_t *src_brickinfo) +{ +        glusterd_conf_t *priv                       = NULL; +        char             mount_point_path[PATH_MAX] = {0,}; +        int              ret                        = -1; + +        priv = THIS->private; + +        snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", +                  priv->workdir, volinfo->volname, +                  RB_CLIENT_MOUNTPOINT); + +        ret = rmdir (mount_point_path); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, "rmdir failed"); +                goto out; +        } + +        ret = 0; + +out: +        return ret; +} + +static int +rb_destroy_maintenance_client (glusterd_volinfo_t *volinfo, +                                glusterd_brickinfo_t *src_brickinfo) +{ +        glusterd_conf_t  *priv                        = NULL; +        runner_t          runner                      = {0,}; +        char              filename[PATH_MAX]          = {0,}; +        struct stat       buf; +        char              mount_point_path[PATH_MAX]  = {0,}; +        int               ret                         = -1; + +        priv = THIS->private; + +        snprintf (mount_point_path, PATH_MAX, "%s/vols/%s/%s", +                  priv->workdir, volinfo->volname, +                  RB_CLIENT_MOUNTPOINT); + +        ret = stat (mount_point_path, &buf); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "stat failed. Cannot destroy maintenance " +                        "client"); +                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); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "umount failed on maintenance client"); +                goto out; +        } + +        ret = rb_mountpoint_rmdir (volinfo, src_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "rmdir of mountpoint failed"); +                goto out; +        } + +        snprintf (filename, PATH_MAX, "%s/vols/%s/%s", +                  priv->workdir, volinfo->volname, +                  RB_CLIENTVOL_FILENAME); + +        ret = unlink (filename); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "unlink failed"); +                goto out; +        } + +        ret = 0; + +out: +        return ret; +} + +static int +rb_spawn_maintenance_client (glusterd_volinfo_t *volinfo, +                             glusterd_brickinfo_t *src_brickinfo) +{ +        int ret = -1; + +        ret = rb_generate_client_volfile (volinfo, src_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, "Unable to generate client " +                        "volfile"); +                goto out; +        } + +        ret = rb_mountpoint_mkdir (volinfo, src_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, "Unable to mkdir " +                        "mountpoint"); +                goto out; +        } + +        ret = rb_spawn_glusterfs_client (volinfo, src_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, "Unable to start glusterfs"); +                goto out; +        } + +        ret = 0; +out: +        return ret; +} + +static int +rb_spawn_destination_brick (glusterd_volinfo_t *volinfo, +                            glusterd_brickinfo_t *dst_brickinfo) + +{ +        int ret = -1; + +        ret = rb_generate_dst_brick_volfile (volinfo, dst_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, "Unable to generate client " +                        "volfile"); +                goto out; +        } + +        ret = rb_spawn_dst_brick (volinfo, dst_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, "Unable to start glusterfs"); +                goto out; +        } + +        ret = 0; +out: +        return ret; +} + +static int +rb_do_operation_start (glusterd_volinfo_t *volinfo, +                       glusterd_brickinfo_t *src_brickinfo, +                       glusterd_brickinfo_t *dst_brickinfo) +{ +        char start_value[8192] = {0,}; +        int ret = -1; + + +        gf_log ("", GF_LOG_DEBUG, +                "replace-brick sending start xattr"); + +        ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "Could not spawn maintenance " +                        "client"); +                goto out; +        } + +	gf_log ("", GF_LOG_DEBUG, +		"mounted the replace brick client"); + +        snprintf (start_value, 8192, "%s:%s:%d", +                  dst_brickinfo->hostname, +                  dst_brickinfo->path, +                  dst_brickinfo->port); + + +        ret = rb_send_xattr_command (volinfo, src_brickinfo, +                                     dst_brickinfo, RB_PUMP_START_CMD, +                                     start_value); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "Failed to send command to pump"); +        } + +        ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "Failed to destroy maintenance " +                        "client"); +                goto out; +        } + +        gf_log ("", GF_LOG_DEBUG, +		"unmounted the replace brick client"); +        ret = 0; + +out: +        return ret; +} + +static int +rb_do_operation_pause (glusterd_volinfo_t *volinfo, +                       glusterd_brickinfo_t *src_brickinfo, +                       glusterd_brickinfo_t *dst_brickinfo) +{ +        int ret = -1; + +        gf_log ("", GF_LOG_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) +{ +        glusterd_conf_t  *priv               = NULL; +        char              pidfile[PATH_MAX]  = {0,}; + +        priv = THIS->private; + +        snprintf (pidfile, PATH_MAX, "%s/vols/%s/%s", +                  priv->workdir, volinfo->volname, +                  RB_DSTBRICK_PIDFILE); + +        return glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_true); +} + +static int +rb_do_operation_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); + +       ret = stat (mount_point_path, &buf); +         if (ret) { +                 gf_log ("", GF_LOG_DEBUG, +                         "stat failed. Could not send " +                         " %s command", xattr_key); +                 goto out; +         } + +        ret = sys_lgetxattr (mount_point_path, xattr_key, value, 8192); + +        if (ret < 0) { +                gf_log ("", GF_LOG_DEBUG, +                        "getxattr failed"); +                goto out; +        } + +        ret = 0; + +out: +        return ret; +} + +static int +rb_do_operation_status (glusterd_volinfo_t *volinfo, +                        glusterd_brickinfo_t *src_brickinfo, +                        glusterd_brickinfo_t *dst_brickinfo) +{ +        char            status[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; +        } + +        origin = _gf_true; + +        if (origin) { +                ret = rb_spawn_maintenance_client (volinfo, src_brickinfo); +                if (ret) { +                        gf_log ("", GF_LOG_DEBUG, +                                "Could not spawn maintenance " +                                "client"); +                        goto out; +                } + +		gf_log ("", GF_LOG_DEBUG, +			"mounted the replace brick client"); + +                ret = rb_get_xattr_command (volinfo, src_brickinfo, +                                            dst_brickinfo, RB_PUMP_STATUS_CMD, +                                            status); +                if (ret) { +                        gf_log ("", GF_LOG_DEBUG, +                                "Failed to get status from pump"); +                        goto umount; +                } + +                gf_log ("", GF_LOG_DEBUG, +                        "pump status is %s", status); + +                status_reply = gf_strdup (status); +                if (!status_reply) { +                        gf_log ("", GF_LOG_ERROR, "Out of memory"); +                        ret = -1; +                        goto umount; +                } + +                ret = dict_set_dynstr (ctx, "status-reply", +                                       status_reply); +                if (ret) { +                        gf_log ("", GF_LOG_DEBUG, +                                "failed to set pump status in ctx"); + +                } + +	umount: +                ret = rb_destroy_maintenance_client (volinfo, src_brickinfo); +                if (ret) { +                        gf_log ("", GF_LOG_DEBUG, +                                "Failed to destroy maintenance " +                                "client"); +			goto out; +		} +        } + +	gf_log ("", GF_LOG_DEBUG, +		"unmounted the replace brick client"); +out: +        return ret; +} + +/* Set src-brick's port number to be used in the maintainance mount + * after all commit acks are received. + */ +static int +rb_update_srcbrick_port (glusterd_brickinfo_t *src_brickinfo, dict_t *rsp_dict, +                         dict_t *req_dict, int32_t replace_op) +{ +        xlator_t *this            = NULL; +        dict_t   *ctx             = NULL; +        int       ret             = 0; +        int       dict_ret        = 0; +        int       src_port        = 0; + +        this = THIS; + +        ctx = glusterd_op_get_ctx (); +        if (ctx) { +                dict_ret = dict_get_int32 (req_dict, "src-brick-port", &src_port); +                if (src_port) +                        src_brickinfo->port = src_port; +        } + +        if (!glusterd_is_local_addr (src_brickinfo->hostname)) { +                gf_log ("", GF_LOG_INFO, +                        "adding src-brick port no"); + +                src_brickinfo->port = pmap_registry_search (this, +                                      src_brickinfo->path, GF_PMAP_PORT_BRICKSERVER); +                if (!src_brickinfo->port && +                    replace_op != GF_REPLACE_OP_COMMIT_FORCE ) { +                        gf_log ("", GF_LOG_ERROR, +                                "Src brick port not available"); +                        ret = -1; +                        goto out; +                } + +                if (rsp_dict) { +                        ret = dict_set_int32 (rsp_dict, "src-brick-port", src_brickinfo->port); +                        if (ret) { +                                gf_log ("", GF_LOG_DEBUG, +                                        "Could not set src-brick port no"); +                                goto out; +                        } +                } + +                ctx = glusterd_op_get_ctx (); +                if (ctx) { +                        ret = dict_set_int32 (ctx, "src-brick-port", src_brickinfo->port); +                        if (ret) { +                                gf_log ("", GF_LOG_DEBUG, +                                        "Could not set src-brick port no"); +                                goto out; +                        } +                } + +        } + +out: +        return ret; + +} + +static int +rb_update_dstbrick_port (glusterd_brickinfo_t *dst_brickinfo, dict_t *rsp_dict, +                         dict_t *req_dict, int32_t replace_op) +{ +        dict_t *ctx           = NULL; +        int     ret           = 0; +        int     dict_ret      = 0; +        int     dst_port      = 0; + +        ctx = glusterd_op_get_ctx (); +        if (ctx) { +                dict_ret = dict_get_int32 (req_dict, "dst-brick-port", &dst_port); +                if (dst_port) +                        dst_brickinfo->port = dst_port; + +        } + +        if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { +                gf_log ("", GF_LOG_INFO, +                        "adding dst-brick port no"); + +                if (rsp_dict) { +                        ret = dict_set_int32 (rsp_dict, "dst-brick-port", +                                              dst_brickinfo->port); +                        if (ret) { +                                gf_log ("", GF_LOG_DEBUG, +                                        "Could not set dst-brick port no in rsp dict"); +                                goto out; +                        } +                } + +                ctx = glusterd_op_get_ctx (); +                if (ctx) { +                        ret = dict_set_int32 (ctx, "dst-brick-port", +                                              dst_brickinfo->port); +                        if (ret) { +                                gf_log ("", GF_LOG_DEBUG, +                                        "Could not set dst-brick port no"); +                                goto out; +                        } +                } +        } +out: +        return ret; +} + +static int +glusterd_op_perform_replace_brick (glusterd_volinfo_t  *volinfo, +                                   char *old_brick, char  *new_brick) +{ +        glusterd_brickinfo_t                    *old_brickinfo = NULL; +        glusterd_brickinfo_t                    *new_brickinfo = NULL; +        int32_t                                 ret = -1; +        glusterd_conf_t                         *priv = NULL; + +        priv = THIS->private; + +        GF_ASSERT (volinfo); + +        ret = glusterd_brickinfo_from_brick (new_brick, +                                             &new_brickinfo); +        if (ret) +                goto out; + +        ret = glusterd_volume_brickinfo_get_by_brick (old_brick, volinfo, +                                                      &old_brickinfo); +        if (ret) +                goto out; + +        ret = glusterd_resolve_brick (new_brickinfo); +        if (ret) +                goto out; + +        list_add_tail (&new_brickinfo->brick_list, +                       &old_brickinfo->brick_list); + +        volinfo->brick_count++; + +        ret = glusterd_op_perform_remove_brick (volinfo, old_brick); +        if (ret) +                goto out; + +        ret = glusterd_create_volfiles_and_notify_services (volinfo); +        if (ret) +                goto out; + +        if (GLUSTERD_STATUS_STARTED == volinfo->status) { +                ret = glusterd_brick_start (volinfo, new_brickinfo); +                if (ret) +                        goto out; +        } + + +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict) +{ +        int                                      ret = 0; +        dict_t                                  *ctx  = NULL; +        int                                      replace_op = 0; +        glusterd_volinfo_t                      *volinfo = NULL; +        char                                    *volname = NULL; +        xlator_t                                *this = NULL; +        glusterd_conf_t                         *priv = NULL; +        char                                    *src_brick = NULL; +        char                                    *dst_brick = NULL; +        glusterd_brickinfo_t                    *src_brickinfo = NULL; +        glusterd_brickinfo_t                    *dst_brickinfo = NULL; + +        this = THIS; +        GF_ASSERT (this); + +        priv = this->private; +        GF_ASSERT (priv); + +        ret = dict_get_str (dict, "src-brick", &src_brick); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); +                goto out; +        } + +        gf_log (this->name, GF_LOG_DEBUG, +                "src brick=%s", src_brick); + +        ret = dict_get_str (dict, "dst-brick", &dst_brick); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get dst brick"); +                goto out; +        } + +        gf_log (this->name, GF_LOG_DEBUG, +                "dst brick=%s", dst_brick); + +        ret = dict_get_str (dict, "volname", &volname); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        ret = dict_get_int32 (dict, "operation", (int32_t *)&replace_op); +        if (ret) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "dict_get on operation failed"); +                goto out; +        } + +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); +                goto out; +        } + +        ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, &src_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, "Unable to get src-brickinfo"); +                goto out; +        } + + +        ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get " +                         "replace brick destination brickinfo"); +                goto out; +        } + +        ret = glusterd_resolve_brick (dst_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); +                goto out; +        } + +        ret = rb_update_srcbrick_port (src_brickinfo, rsp_dict, +                                       dict, replace_op); +        if (ret) +                goto out; + +	if ((GF_REPLACE_OP_START != replace_op)) { +                ret = rb_update_dstbrick_port (dst_brickinfo, rsp_dict, +                                               dict, replace_op); +                if (ret) +                        goto out; +	} + +        switch (replace_op) { +        case GF_REPLACE_OP_START: +        { +                if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { +                        gf_log ("", GF_LOG_INFO, +                                "I AM THE DESTINATION HOST"); +                        if (!glusterd_is_rb_paused (volinfo)) { +                                ret = rb_spawn_destination_brick (volinfo, dst_brickinfo); +                                if (ret) { +                                        gf_log ("", GF_LOG_DEBUG, +                                                "Failed to spawn destination brick"); +                                        goto out; +                                } +                        } else { +                                gf_log ("", GF_LOG_ERROR, "Replace brick is already " +                                        "started=> no need to restart dst brick "); +                        } +		} + + +		if (!glusterd_is_local_addr (src_brickinfo->hostname)) { +		        ret = rb_src_brick_restart (volinfo, src_brickinfo, +				                    1); +		        if (ret) { +				gf_log ("", GF_LOG_DEBUG, +	                        "Could not restart src-brick"); +			        goto out; +			} +		} + +		if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { +			gf_log ("", GF_LOG_INFO, +				"adding dst-brick port no"); + +                        ret = rb_update_dstbrick_port (dst_brickinfo, rsp_dict, +                                                       dict, replace_op); +                        if (ret) +                                goto out; +                } + +                glusterd_set_rb_status (volinfo, GF_RB_STATUS_STARTED); +		break; +	} + +        case GF_REPLACE_OP_COMMIT: +        case GF_REPLACE_OP_COMMIT_FORCE: +        { +                ctx = glusterd_op_get_ctx (); +                if (ctx) { +                        ret = rb_do_operation_commit (volinfo, src_brickinfo, dst_brickinfo); +                        if (ret) { +                                gf_log ("", GF_LOG_ERROR, +                                        "Commit operation failed"); +                                goto out; +                        } +                } + +                ret = dict_set_int32 (volinfo->dict, "enable-pump", 0); +                gf_log ("", GF_LOG_DEBUG, +                        "Received commit - will be adding dst brick and " +                        "removing src brick"); + +                if (!glusterd_is_local_addr (dst_brickinfo->hostname) && +                    replace_op != GF_REPLACE_OP_COMMIT_FORCE) { +                        gf_log ("", GF_LOG_INFO, +                                "I AM THE DESTINATION HOST"); +                        ret = rb_kill_destination_brick (volinfo, dst_brickinfo); +                        if (ret) { +                                gf_log ("", GF_LOG_DEBUG, +                                        "Failed to kill destination brick"); +                                goto out; +                        } +                } + +                if (ret) { +                        gf_log ("", GF_LOG_CRITICAL, +                                "Unable to cleanup dst brick"); +                        goto out; +                } + + +                ret = glusterd_nfs_server_stop (); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, +                                "Unable to stop nfs server, ret: %d", ret); +                } + +		ret = glusterd_op_perform_replace_brick (volinfo, src_brick, +							 dst_brick); +		if (ret) { +			gf_log ("", GF_LOG_CRITICAL, "Unable to add " +				"dst-brick: %s to volume: %s", +				dst_brick, volinfo->volname); +		        (void) glusterd_check_generate_start_nfs (); +			goto out; +		} + +		volinfo->defrag_status = 0; + +		ret = glusterd_check_generate_start_nfs (); +		if (ret) { +                        gf_log ("", GF_LOG_CRITICAL, +                                "Failed to generate nfs volume file"); +		} + + +		ret = glusterd_fetchspec_notify (THIS); +                glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); +                glusterd_brickinfo_delete (volinfo->dst_brick); +                volinfo->src_brick = volinfo->dst_brick = NULL; +        } +        break; + +        case GF_REPLACE_OP_PAUSE: +        { +                gf_log ("", GF_LOG_DEBUG, +                        "Received pause - doing nothing"); +                ctx = glusterd_op_get_ctx (); +                if (ctx) { +                        ret = rb_do_operation_pause (volinfo, src_brickinfo, +                                                     dst_brickinfo); +                        if (ret) { +                                gf_log ("", GF_LOG_ERROR, +                                        "Pause operation failed"); +                                goto out; +                        } +                } + +                glusterd_set_rb_status (volinfo, GF_RB_STATUS_PAUSED); +        } +                break; + +        case GF_REPLACE_OP_ABORT: +        { + +                ctx = glusterd_op_get_ctx (); +                if (ctx) { +                        ret = rb_do_operation_abort (volinfo, src_brickinfo, dst_brickinfo); +                        if (ret) { +                                gf_log (THIS->name, GF_LOG_ERROR, +                                        "Abort operation failed"); +                                goto out; +                        } +                } + +                ret = dict_set_int32 (volinfo->dict, "enable-pump", 0); +		if (ret) { +			gf_log (THIS->name, GF_LOG_CRITICAL, "Unable to disable pump"); +		} + + +                if (!glusterd_is_local_addr (dst_brickinfo->hostname)) { +                        gf_log (THIS->name, GF_LOG_INFO, +                                "I AM THE DESTINATION HOST"); +                        ret = rb_kill_destination_brick (volinfo, dst_brickinfo); +                        if (ret) { +                                gf_log ("", GF_LOG_DEBUG, +                                        "Failed to kill destination brick"); +                                goto out; +                        } +                } +                glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); +                glusterd_brickinfo_delete (volinfo->dst_brick); +                volinfo->src_brick = volinfo->dst_brick = NULL; +        } +        break; + +        case GF_REPLACE_OP_STATUS: +        { +                gf_log ("", GF_LOG_DEBUG, +                        "received status - doing nothing"); +                ctx = glusterd_op_get_ctx (); +                if (ctx) { +                        if (glusterd_is_rb_paused (volinfo)) { +                                ret = dict_set_str (ctx, "status-reply", +                                                 "replace brick has been paused"); +                                if (ret) +                                        gf_log (THIS->name, GF_LOG_ERROR, +                                                "failed to set pump status" +                                                "in ctx"); +                                goto out; +                        } + +                        ret = rb_do_operation_status (volinfo, src_brickinfo, +                                                      dst_brickinfo); +                        if (ret) +                                goto out; +                } + +        } +                break; + +        default: +                ret = -1; +                goto out; +        } +        if (!ret && replace_op != GF_REPLACE_OP_STATUS) +		ret = glusterd_store_volinfo (volinfo, +                                              GLUSTERD_VOLINFO_VER_AC_INCREMENT); +        if (ret) +                gf_log (THIS->name, GF_LOG_ERROR, "Couldn't store" +                        " replace brick operation's state"); + +out: +        return ret; +} + +void +glusterd_do_replace_brick (void *data) +{ +        glusterd_volinfo_t     *volinfo = NULL; +        int32_t                 op      = 0; +        int32_t                 src_port = 0; +        int32_t                 dst_port = 0; +        dict_t                 *dict    = NULL; +        char                   *src_brick = NULL; +        char                   *dst_brick = NULL; +        char                   *volname   = NULL; +        glusterd_brickinfo_t   *src_brickinfo = NULL; +        glusterd_brickinfo_t   *dst_brickinfo = NULL; +	glusterd_conf_t	       *priv = NULL; + +        int ret = 0; + +        dict = data; + +	GF_ASSERT (THIS); + +	priv = THIS->private; + +	if (priv->timer) { +		gf_timer_call_cancel (THIS->ctx, priv->timer); +		priv->timer = NULL; +                gf_log ("", GF_LOG_DEBUG, +                        "Cancelled timer thread"); +	} + +        gf_log ("", GF_LOG_DEBUG, +                "Replace brick operation detected"); + +        ret = dict_get_int32 (dict, "operation", &op); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, +                        "dict_get on operation failed"); +                goto out; +        } +        ret = dict_get_str (dict, "src-brick", &src_brick); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get src brick"); +                goto out; +        } + +        gf_log ("", GF_LOG_DEBUG, +                "src brick=%s", src_brick); + +        ret = dict_get_str (dict, "dst-brick", &dst_brick); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get dst brick"); +                goto out; +        } + +        gf_log ("", GF_LOG_DEBUG, +                "dst brick=%s", dst_brick); + +        ret = dict_get_str (dict, "volname", &volname); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); +                goto out; +        } + +        ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo, &src_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, "Unable to get src-brickinfo"); +                goto out; +        } + +        ret = glusterd_get_rb_dst_brickinfo (volinfo, &dst_brickinfo); +        if (!dst_brickinfo) { +                gf_log ("", GF_LOG_DEBUG, "Unable to get dst-brickinfo"); +                goto out; +        } + +        ret = glusterd_resolve_brick (dst_brickinfo); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, "Unable to resolve dst-brickinfo"); +                goto out; +        } + +        ret = dict_get_int32 (dict, "src-brick-port", &src_port); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get src-brick port"); +                goto out; +        } + +        ret = dict_get_int32 (dict, "dst-brick-port", &dst_port); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get dst-brick port"); +        } + +        dst_brickinfo->port = dst_port; +        src_brickinfo->port = src_port; + +        switch (op) { +        case GF_REPLACE_OP_START: +                if (!dst_port) { +                        ret = -1; +                        goto out; +                } + +                ret = rb_do_operation_start (volinfo, src_brickinfo, dst_brickinfo); +                if (ret) { +                        glusterd_set_rb_status (volinfo, GF_RB_STATUS_NONE); +                        goto out; +                } +                break; +        case GF_REPLACE_OP_PAUSE: +        case GF_REPLACE_OP_ABORT: +        case GF_REPLACE_OP_COMMIT: +        case GF_REPLACE_OP_COMMIT_FORCE: +        case GF_REPLACE_OP_STATUS: +                break; +        default: +                ret = -1; +                goto out; +        } + +out: +        if (ret) +                ret = glusterd_op_sm_inject_event (GD_OP_EVENT_RCVD_RJT, NULL); +        else +                ret = glusterd_op_sm_inject_event (GD_OP_EVENT_COMMIT_ACC, NULL); + +        if (dict) +                dict_unref (dict); + +        glusterd_op_sm (); +} diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c new file mode 100644 index 000000000..1e4670304 --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c @@ -0,0 +1,1038 @@ +/* +  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/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "cli1.h" +#include "glusterd.h" +#include "glusterd-op-sm.h" +#include "glusterd-store.h" +#include "glusterd-utils.h" +#include "glusterd-volgen.h" +#include "run.h" + +#define glusterd_op_start_volume_args_get(dict, volname, flags) \ +        glusterd_op_stop_volume_args_get (dict, volname, flags) + +int +glusterd_handle_create_volume (rpcsvc_request_t *req) +{ +        int32_t                 ret         = -1; +        gf1_cli_create_vol_req  cli_req     = {0,}; +        dict_t                 *dict        = NULL; +        glusterd_brickinfo_t   *brickinfo   = NULL; +        char                   *brick       = NULL; +        char                   *bricks      = NULL; +        char                   *volname     = NULL; +        int                    brick_count = 0; +        char                   *tmpptr      = NULL; +        int                    i           = 0; +        char                   *brick_list  = NULL; +        void                   *cli_rsp     = NULL; +        char                    err_str[2048] = {0,}; +        gf1_cli_create_vol_rsp  rsp         = {0,}; +        glusterd_conf_t        *priv        = NULL; +        xlator_t               *this        = NULL; +        char                   *free_ptr    = NULL; +        char                   *trans_type  = NULL; +        uuid_t                  volume_id   = {0,}; +        glusterd_brickinfo_t    *tmpbrkinfo = NULL; +        glusterd_volinfo_t      tmpvolinfo = {{0},}; + +        GF_ASSERT (req); + +        INIT_LIST_HEAD (&tmpvolinfo.bricks); + +        this = THIS; +        GF_ASSERT(this); + +        priv = this->private; + +        ret = -1; +        if (!gf_xdr_to_cli_create_vol_req (req->msg[0], &cli_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                snprintf (err_str, sizeof (err_str), "Garbage args received"); +                goto out; +        } + +        gf_log ("glusterd", GF_LOG_INFO, "Received create volume req"); + +        if (cli_req.bricks.bricks_len) { +                /* Unserialize the dictionary */ +                dict  = dict_new (); + +                ret = dict_unserialize (cli_req.bricks.bricks_val, +                                        cli_req.bricks.bricks_len, +                                        &dict); +                if (ret < 0) { +                        gf_log ("glusterd", GF_LOG_ERROR, +                                "failed to " +                                "unserialize req-buffer to dictionary"); +                        snprintf (err_str, sizeof (err_str), "Unable to decode " +                                  "the buffer"); +                        goto out; +                } else { +                        dict->extra_stdfree = cli_req.bricks.bricks_val; +                } +        } + +        ret = dict_get_str (dict, "volname", &volname); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                snprintf (err_str, sizeof (err_str), "Unable to get volume " +                          "name"); +                goto out; +        } +        gf_cmd_log ("Volume create", "on volname: %s attempted", volname); + +        if ((ret = glusterd_check_volume_exists (volname))) { +                snprintf(err_str, 2048, "Volume %s already exists", volname); +                gf_log ("glusterd", GF_LOG_ERROR, "%s", err_str); +                goto out; +        } + +        ret = dict_get_int32 (dict, "count", &brick_count); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get count"); +                snprintf (err_str, sizeof (err_str), "Unable to get volume " +                          "brick count"); +                goto out; +        } + +        ret = dict_get_str (dict, "transport", &trans_type); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get transport-type"); +                snprintf (err_str, sizeof (err_str), "Unable to get volume " +                          "transport-type"); +                goto out; +        } +        ret = dict_get_str (dict, "bricks", &bricks); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); +                snprintf (err_str, sizeof (err_str), "Unable to get volume " +                          "bricks"); +                goto out; +        } + +        uuid_generate (volume_id); +        free_ptr = gf_strdup (uuid_utoa (volume_id)); +        ret = dict_set_dynstr (dict, "volume-id", free_ptr); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "unable to set volume-id"); +                snprintf (err_str, sizeof (err_str), "Unable to set volume " +                          "id"); +                goto out; +        } +        free_ptr = NULL; + +        if (bricks) { +                brick_list = gf_strdup (bricks); +                free_ptr = brick_list; +        } + +        gf_cmd_log ("Volume create", "on volname: %s type:%s count:%d bricks:%s", +                    cli_req.volname, ((cli_req.type == 0)? "DEFAULT": +                    ((cli_req.type == 1)? "STRIPE":"REPLICATE")), cli_req.count, +                    bricks); + + +        while ( i < brick_count) { +                i++; +                brick= strtok_r (brick_list, " \n", &tmpptr); +                brick_list = tmpptr; +                ret = glusterd_brickinfo_from_brick (brick, &brickinfo); +                if (ret) { +                        snprintf (err_str, sizeof (err_str), "Unable to get " +                                  "brick info from brick %s", brick); +                        goto out; +                } + +                ret = glusterd_new_brick_validate (brick, brickinfo, err_str, +                                                   sizeof (err_str)); +                if (ret) +                        goto out; +                ret = glusterd_volume_brickinfo_get (brickinfo->uuid, +                                                     brickinfo->hostname, +                                                     brickinfo->path, +                                                     &tmpvolinfo, &tmpbrkinfo); +                if (!ret) { +                        ret = -1; +                        snprintf (err_str, sizeof (err_str), "Brick: %s:%s, %s" +                                  " one of the arguments contain the other", +                                  tmpbrkinfo->hostname, tmpbrkinfo->path, brick); +                        goto out; +                } +                list_add_tail (&brickinfo->brick_list, &tmpvolinfo.bricks); +                brickinfo = NULL; +        } + +        ret = glusterd_op_begin (req, GD_OP_CREATE_VOLUME, dict); +        gf_cmd_log ("Volume create", "on volname: %s %s", volname, +                    (ret != 0) ? "FAILED": "SUCCESS"); + +out: +        if (ret) { +                if (dict) +                        dict_unref (dict); +                rsp.op_ret = -1; +                rsp.op_errno = 0; +                rsp.volname = ""; +                if (err_str[0] == '\0') +                        snprintf (err_str, sizeof (err_str), "Operation failed"); +                rsp.op_errstr = err_str; +                cli_rsp = &rsp; +                glusterd_submit_reply(req, cli_rsp, NULL, 0, NULL, +                                      gf_xdr_serialize_cli_create_vol_rsp, +                                      (xdrproc_t)xdr_gf1_cli_create_vol_rsp); + +                ret = 0; //Client response sent, prevent second response +        } + +        if (free_ptr) +                GF_FREE(free_ptr); + +        glusterd_volume_brickinfos_delete (&tmpvolinfo); +        if (brickinfo) +                glusterd_brickinfo_delete (brickinfo); +        if (cli_req.volname) +                free (cli_req.volname); // its a malloced by xdr + +        glusterd_friend_sm (); +        glusterd_op_sm (); + +        return ret; +} + +int +glusterd_handle_cli_start_volume (rpcsvc_request_t *req) +{ +        int32_t                         ret = -1; +        gf1_cli_start_vol_req           cli_req = {0,}; +        char                            *dup_volname = NULL; +        dict_t                          *dict = NULL; +        glusterd_op_t                   cli_op = GD_OP_START_VOLUME; + +        GF_ASSERT (req); + +        if (!gf_xdr_to_cli_start_vol_req (req->msg[0], &cli_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        gf_log ("glusterd", GF_LOG_INFO, "Received start vol req" +                "for volume %s", cli_req.volname); + +        dict = dict_new (); + +        if (!dict) +                goto out; + +        dup_volname = gf_strdup (cli_req.volname); +        if (!dup_volname) +                goto out; + +        ret = dict_set_dynstr (dict, "volname", dup_volname); +        if (ret) +                goto out; + +        ret = dict_set_int32 (dict, "flags", cli_req.flags); +        if (ret) +                goto out; +        ret = glusterd_op_begin (req, GD_OP_START_VOLUME, dict); + +        gf_cmd_log ("volume start","on volname: %s %s", cli_req.volname, +                    ((ret == 0) ? "SUCCESS": "FAILED")); + +out: +        if (ret && dict) +                dict_unref (dict); +        if (cli_req.volname) +                free (cli_req.volname); //its malloced by xdr + +        glusterd_friend_sm (); +        glusterd_op_sm (); + +        if (ret) +                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, +                                                     NULL, "operation failed"); + +        return ret; +} + + +int +glusterd_handle_cli_stop_volume (rpcsvc_request_t *req) +{ +        int32_t                         ret = -1; +        gf1_cli_stop_vol_req           cli_req = {0,}; +        char                            *dup_volname = NULL; +        dict_t                          *dict = NULL; +        glusterd_op_t                   cli_op = GD_OP_STOP_VOLUME; + +        GF_ASSERT (req); + +        if (!gf_xdr_to_cli_stop_vol_req (req->msg[0], &cli_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        gf_log ("glusterd", GF_LOG_INFO, "Received stop vol req" +                "for volume %s", cli_req.volname); + +        dict = dict_new (); + +        if (!dict) +                goto out; + +        dup_volname = gf_strdup (cli_req.volname); +        if (!dup_volname) +                goto out; + +        ret = dict_set_dynstr (dict, "volname", dup_volname); +        if (ret) +                goto out; + +        ret = dict_set_int32 (dict, "flags", cli_req.flags); +        if (ret) +                goto out; + +        ret = glusterd_op_begin (req, GD_OP_STOP_VOLUME, dict); +        gf_cmd_log ("Volume stop","on volname: %s %s", cli_req.volname, +                    ((ret)?"FAILED":"SUCCESS")); + +out: +        if (cli_req.volname) +                free (cli_req.volname); //its malloced by xdr + +        glusterd_friend_sm (); +        glusterd_op_sm (); + +        if (ret) { +                if (dict) +                        dict_unref (dict); +                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, +                                                     NULL, "operation failed"); +        } + +        return ret; +} + +int +glusterd_handle_cli_delete_volume (rpcsvc_request_t *req) +{ +        int32_t                           ret = -1; +        gf1_cli_delete_vol_req            cli_req = {0,}; +        glusterd_op_delete_volume_ctx_t   *ctx = NULL; +        glusterd_op_t                     cli_op = GD_OP_DELETE_VOLUME; + +        GF_ASSERT (req); + +        if (!gf_xdr_to_cli_delete_vol_req (req->msg[0], &cli_req)) { +                //failed to decode msg; +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } +        gf_cmd_log ("Volume delete","on volname: %s attempted", cli_req.volname); + +        gf_log ("glusterd", GF_LOG_INFO, "Received delete vol req" +                "for volume %s", cli_req.volname); + + +        ctx = GF_CALLOC (1, sizeof (*ctx), gf_gld_mt_delete_volume_ctx_t); +        if (!ctx) +                goto out; + +        strncpy (ctx->volume_name, cli_req.volname, GD_VOLUME_NAME_MAX); + +        ret = glusterd_op_begin (req, GD_OP_DELETE_VOLUME, ctx); +        gf_cmd_log ("Volume delete", "on volname: %s %s", cli_req.volname, +                   ((ret) ? "FAILED" : "SUCCESS")); + +out: +        if (cli_req.volname) +                free (cli_req.volname); //its malloced by xdr + +        glusterd_friend_sm (); +        glusterd_op_sm (); + +        if (ret) { +                if (ctx) +                        GF_FREE (ctx); + +                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, +                                                     NULL, "operation failed"); +        } + +        return ret; +} + +/* op-sm */ +int +glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr) +{ +        int                                     ret = 0; +        char                                    *volname = NULL; +        gf_boolean_t                            exists = _gf_false; +        char                                    *bricks = NULL; +        char                                    *brick_list = NULL; +        char                                    *free_ptr = NULL; +        glusterd_brickinfo_t                    *brick_info = NULL; +        int32_t                                 brick_count = 0; +        int32_t                                 i = 0; +        char                                    *brick = NULL; +        char                                    *tmpptr = NULL; +        char                                    cmd_str[1024]; +        xlator_t                                *this = NULL; +        glusterd_conf_t                         *priv = NULL; +        char                                    msg[2048] = {0}; +        uuid_t                                  volume_uuid; +        char                                    *volume_uuid_str; + +        this = THIS; +        if (!this) { +                gf_log ("glusterd", GF_LOG_ERROR, +                        "this is NULL"); +                goto out; +        } + +        priv = this->private; +        if (!priv) { +                gf_log ("glusterd", GF_LOG_ERROR, +                        "priv is NULL"); +                goto out; +        } + +        ret = dict_get_str (dict, "volname", &volname); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        exists = glusterd_check_volume_exists (volname); + +        if (exists) { +                snprintf (msg, sizeof (msg), "Volume %s already exists", +                          volname); +                gf_log ("", GF_LOG_ERROR, "%s", msg); +                *op_errstr = gf_strdup (msg); +                ret = -1; +                goto out; +        } else { +                ret = 0; +        } +        ret = dict_get_int32 (dict, "count", &brick_count); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get count"); +                goto out; +        } +        ret = dict_get_str (dict, "volume-id", &volume_uuid_str); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume id"); +                goto out; +        } +        ret = uuid_parse (volume_uuid_str, volume_uuid); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to parse volume id"); +                goto out; +        } + +        ret = dict_get_str (dict, "bricks", &bricks); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); +                goto out; +        } + +        if (bricks) { +                brick_list = gf_strdup (bricks); +                if (!brick_list) { +                        ret = -1; +                        gf_log ("", GF_LOG_ERROR, "Out of memory"); +                        goto out; +                } else { +                        free_ptr = brick_list; +                } +        } + +        while ( i < brick_count) { +                i++; +                brick= strtok_r (brick_list, " \n", &tmpptr); +                brick_list = tmpptr; + +                if (!glusterd_store_is_valid_brickpath (volname, brick) || +                        !glusterd_is_valid_volfpath (volname, brick)) { +                        snprintf (msg, sizeof (msg), "brick path %s is too " +                                  "long.", brick); +                        gf_log ("", GF_LOG_ERROR, "%s", msg); +                        *op_errstr = gf_strdup (msg); + +                        ret = -1; +                        goto out; +                } + +                ret = glusterd_brickinfo_from_brick (brick, &brick_info); +                if (ret) +                        goto out; +                snprintf (cmd_str, 1024, "%s", brick_info->path); +                ret = glusterd_resolve_brick (brick_info); +                if (ret) { +                        gf_log ("glusterd", GF_LOG_ERROR, "cannot resolve " +                                "brick: %s:%s", brick_info->hostname, +                                brick_info->path); +                        goto out; +                } + +                if (!uuid_compare (brick_info->uuid, priv->uuid)) { +                        ret = glusterd_brick_create_path (brick_info->hostname, +                                                          brick_info->path, +                                                          volume_uuid, +                                                          0777, op_errstr); +                        if (ret) +                                goto out; +                        brick_list = tmpptr; +                } +                glusterd_brickinfo_delete (brick_info); +                brick_info = NULL; +        } +out: +        if (free_ptr) +                GF_FREE (free_ptr); +        if (brick_info) +                glusterd_brickinfo_delete (brick_info); +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +        return ret; +} + +int +glusterd_op_stop_volume_args_get (dict_t *dict, char** volname, int *flags) +{ +        int ret = -1; + +        if (!dict || !volname || !flags) +                goto out; + +        ret = dict_get_str (dict, "volname", volname); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        ret = dict_get_int32 (dict, "flags", flags); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get flags"); +                goto out; +        } +out: +        return ret; +} + +int +glusterd_op_stage_start_volume (dict_t *dict, char **op_errstr) +{ +        int                                     ret = 0; +        char                                    *volname = NULL; +        int                                     flags = 0; +        gf_boolean_t                            exists = _gf_false; +        glusterd_volinfo_t                      *volinfo = NULL; +        glusterd_brickinfo_t                    *brickinfo = NULL; +        char                                    msg[2048]; +        glusterd_conf_t                         *priv = NULL; + +        priv = THIS->private; +        if (!priv) { +                gf_log ("glusterd", GF_LOG_ERROR, +                        "priv is NULL"); +                ret = -1; +                goto out; +        } + +        ret = glusterd_op_start_volume_args_get (dict, &volname, &flags); +        if (ret) +                goto out; + +        exists = glusterd_check_volume_exists (volname); + +        if (!exists) { +                snprintf (msg, sizeof (msg), "Volume %s does not exist", volname); +                gf_log ("", GF_LOG_ERROR, "%s", +                        msg); +                *op_errstr = gf_strdup (msg); +                ret = -1; +        } else { +                ret = 0; +        } + +        ret  = glusterd_volinfo_find (volname, &volinfo); + +        if (ret) +                goto out; + +        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { +                ret = glusterd_resolve_brick (brickinfo); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, +                                "Unable to resolve brick %s:%s", +                                brickinfo->hostname, brickinfo->path); +                        goto out; +                } + +                if (!uuid_compare (brickinfo->uuid, priv->uuid)) { +                        ret = glusterd_brick_create_path (brickinfo->hostname, +                                                          brickinfo->path, +                                                          volinfo->volume_id, +                                                          0777, op_errstr); +                        if (ret) +                                goto out; +                } + +                if (!(flags & GF_CLI_FLAG_OP_FORCE)) { +                        if (glusterd_is_volume_started (volinfo)) { +                                snprintf (msg, sizeof (msg), "Volume %s already" +                                          " started", volname); +                                gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); +                                *op_errstr = gf_strdup (msg); +                                ret = -1; +                                goto out; +                        } +                } +        } + +        ret = 0; +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +        return ret; +} + +int +glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr) +{ +        int                                     ret = -1; +        char                                    *volname = NULL; +        int                                     flags = 0; +        gf_boolean_t                            exists = _gf_false; +        gf_boolean_t                            is_run = _gf_false; +        glusterd_volinfo_t                      *volinfo = NULL; +        char                                    msg[2048] = {0}; + + +        ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags); +        if (ret) +                goto out; + +        exists = glusterd_check_volume_exists (volname); + +        if (!exists) { +                snprintf (msg, sizeof (msg), "Volume %s does not exist", volname); +                gf_log ("", GF_LOG_ERROR, "%s", msg); +                *op_errstr = gf_strdup (msg); +                ret = -1; +                goto out; +        } else { +                ret = 0; +        } + +        ret  = glusterd_volinfo_find (volname, &volinfo); + +        if (ret) +                goto out; + +        if (!(flags & GF_CLI_FLAG_OP_FORCE)) { +                if (_gf_false == glusterd_is_volume_started (volinfo)) { +                        snprintf (msg, sizeof(msg), "Volume %s " +                                  "is not in the started state", volname); +                        gf_log ("", GF_LOG_ERROR, "Volume %s " +                                "has not been started", volname); +                        *op_errstr = gf_strdup (msg); +                        ret = -1; +                        goto out; +                } +                ret = glusterd_check_gsync_running (volinfo, &is_run); +                if (ret && (is_run == _gf_false)) +                        gf_log ("", GF_LOG_WARNING, "Unable to get the status" +                                 " of active "GEOREP" session"); +                if (is_run) { +                        gf_log ("", GF_LOG_WARNING, GEOREP" sessions active" +                                "for the volume %s ", volname); +                        snprintf (msg, sizeof(msg), GEOREP" sessions are active " +                                  "for the volume '%s'.\nUse 'volume "GEOREP" " +                                  "status' command for more info. Use 'force'" +                                  "option to ignore and stop stop the volume", +                                   volname); +                        *op_errstr = gf_strdup (msg); +                        ret = -1; +                        goto out; +                } + +        } + + +out: + +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +        return ret; +} + +int +glusterd_op_stage_delete_volume (dict_t *dict, char **op_errstr) +{ +        int                                     ret = 0; +        char                                    *volname = NULL; +        gf_boolean_t                            exists = _gf_false; +        glusterd_volinfo_t                      *volinfo = NULL; +        char                                    msg[2048] = {0}; + +        ret = dict_get_str (dict, "volname", &volname); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        exists = glusterd_check_volume_exists (volname); + +        if (!exists) { +                snprintf (msg, sizeof (msg), "Volume %s does not exist", +                          volname); +                gf_log ("", GF_LOG_ERROR, "%s", msg); +                *op_errstr = gf_strdup (msg); +                ret = -1; +                goto out; +        } else { +                ret = 0; +        } + +        ret  = glusterd_volinfo_find (volname, &volinfo); + +        if (ret) +                goto out; + +        if (glusterd_is_volume_started (volinfo)) { +                snprintf (msg, sizeof (msg), "Volume %s has been started." +                          "Volume needs to be stopped before deletion.", +                          volname); +                gf_log ("", GF_LOG_ERROR, "%s", msg); +                *op_errstr = gf_strdup (msg); +                ret = -1; +                goto out; +        } + +        ret = 0; + +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + +        return ret; +} + +int +glusterd_op_create_volume (dict_t *dict, char **op_errstr) +{ +        int                   ret        = 0; +        char                 *volname    = NULL; +        glusterd_conf_t      *priv       = NULL; +        glusterd_volinfo_t   *volinfo    = NULL; +        gf_boolean_t          vol_added = _gf_false; +        glusterd_brickinfo_t *brickinfo  = NULL; +        xlator_t             *this       = NULL; +        char                 *brick      = NULL; +        int32_t               count      = 0; +        int32_t               i          = 1; +        char                 *bricks     = NULL; +        char                 *brick_list = NULL; +        char                 *free_ptr   = NULL; +        char                 *saveptr    = NULL; +        int32_t               sub_count  = 0; +        char                 *trans_type = NULL; +        char                 *str        = NULL; + +        this = THIS; +        GF_ASSERT (this); + +        priv = this->private; +        GF_ASSERT (priv); + +        ret = glusterd_volinfo_new (&volinfo); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to allocate memory"); +                goto out; +        } + +        ret = dict_get_str (dict, "volname", &volname); + +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        strncpy (volinfo->volname, volname, GLUSTERD_MAX_VOLUME_NAME); +        GF_ASSERT (volinfo->volname); + +        ret = dict_get_int32 (dict, "type", &volinfo->type); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get type"); +                goto out; +        } + +        ret = dict_get_int32 (dict, "count", &volinfo->brick_count); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get count"); +                goto out; +        } + +        ret = dict_get_int32 (dict, "port", &volinfo->port); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get port"); +                goto out; +        } + +        count = volinfo->brick_count; + +        ret = dict_get_str (dict, "bricks", &bricks); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get bricks"); +                goto out; +        } + +        if (GF_CLUSTER_TYPE_REPLICATE == volinfo->type) { +                ret = dict_get_int32 (dict, "replica-count", +                                      &sub_count); +                if (ret) +                        goto out; +        } else if (GF_CLUSTER_TYPE_STRIPE == volinfo->type) { +                ret = dict_get_int32 (dict, "stripe-count", +                                      &sub_count); +                if (ret) +                        goto out; +        } else if (GF_CLUSTER_TYPE_STRIPE_REPLICATE == volinfo->type) { +                ret = dict_get_int32 (dict, "stripe-count", +                                      &volinfo->stripe_count); +                if (ret) +                        goto out; +                ret = dict_get_int32 (dict, "replica-count", +                                      &volinfo->replica_count); +                if (ret) +                        goto out; + +                sub_count = volinfo->stripe_count * volinfo->replica_count; +        } + +        ret = dict_get_str (dict, "transport", &trans_type); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get transport"); +                goto out; +        } + +        ret = dict_get_str (dict, "volume-id", &str); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume-id"); +                goto out; +        } +        ret = uuid_parse (str, volinfo->volume_id); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "unable to parse uuid %s", str); +                goto out; +        } + +        if (strcasecmp (trans_type, "rdma") == 0) { +                volinfo->transport_type = GF_TRANSPORT_RDMA; +                volinfo->nfs_transport_type = GF_TRANSPORT_RDMA; +        } else if (strcasecmp (trans_type, "tcp") == 0) { +                volinfo->transport_type = GF_TRANSPORT_TCP; +                volinfo->nfs_transport_type = GF_TRANSPORT_TCP; +        } else { +                volinfo->transport_type = GF_TRANSPORT_BOTH_TCP_RDMA; +                volinfo->nfs_transport_type = GF_DEFAULT_NFS_TRANSPORT; +        } + +        volinfo->sub_count = sub_count; + +        if (bricks) { +                brick_list = gf_strdup (bricks); +                free_ptr = brick_list; +        } + +        if (count) +                brick = strtok_r (brick_list+1, " \n", &saveptr); + +        while ( i <= count) { +                ret = glusterd_brickinfo_from_brick (brick, &brickinfo); +                if (ret) +                        goto out; + +                ret = glusterd_resolve_brick (brickinfo); +                if (ret) +                        goto out; +                list_add_tail (&brickinfo->brick_list, &volinfo->bricks); +                brick = strtok_r (NULL, " \n", &saveptr); +                i++; +        } + +        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); +        if (ret) { +                glusterd_store_delete_volume (volinfo); +                *op_errstr = gf_strdup ("Failed to store the Volume information"); +                goto out; +        } + +        ret = glusterd_create_volfiles_and_notify_services (volinfo); +        if (ret) { +                *op_errstr = gf_strdup ("Failed to create volume files"); +                goto out; +        } + +        ret = glusterd_volume_compute_cksum (volinfo); +        if (ret) { +                *op_errstr = gf_strdup ("Failed to compute checksum of volume"); +                goto out; +        } + +        volinfo->defrag_status = 0; +        list_add_tail (&volinfo->vol_list, &priv->volumes); +        vol_added = _gf_true; +out: +        if (free_ptr) +                GF_FREE(free_ptr); +        if (!vol_added && volinfo) +                glusterd_volinfo_delete (volinfo); +        return ret; +} + +int +glusterd_op_start_volume (dict_t *dict, char **op_errstr) +{ +        int                                     ret = 0; +        char                                    *volname = NULL; +        int                                     flags = 0; +        glusterd_volinfo_t                      *volinfo = NULL; +        glusterd_brickinfo_t                    *brickinfo = NULL; + +        ret = glusterd_op_start_volume_args_get (dict, &volname, &flags); +        if (ret) +                goto out; + +        ret  = glusterd_volinfo_find (volname, &volinfo); + +        if (ret) +                goto out; +        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { +                ret = glusterd_brick_start (volinfo, brickinfo); +                if (ret) +                        goto out; +        } + +        glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STARTED); + +        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); +        if (ret) +                goto out; + +        ret = glusterd_check_generate_start_nfs (); + +out: +        gf_log ("", GF_LOG_DEBUG, "returning %d ", ret); +        return ret; +} + + +int +glusterd_op_stop_volume (dict_t *dict) +{ +        int                                     ret = 0; +        int                                     flags = 0; +        char                                    *volname = NULL; +        glusterd_volinfo_t                      *volinfo = NULL; +        glusterd_brickinfo_t                    *brickinfo = NULL; + +        ret = glusterd_op_stop_volume_args_get (dict, &volname, &flags); +        if (ret) +                goto out; + +        ret  = glusterd_volinfo_find (volname, &volinfo); + +        if (ret) +                goto out; + +        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { +                ret = glusterd_brick_stop (volinfo, brickinfo); +                if (ret) +                        goto out; +        } + +        glusterd_set_volume_status (volinfo, GLUSTERD_STATUS_STOPPED); + +        ret = glusterd_store_volinfo (volinfo, GLUSTERD_VOLINFO_VER_AC_INCREMENT); +        if (ret) +                goto out; + +        if (glusterd_are_all_volumes_stopped ()) { +                if (glusterd_is_nfs_started ()) { +                        ret = glusterd_nfs_server_stop (); +                        if (ret) +                                goto out; +                } +        } else { +                ret = glusterd_check_generate_start_nfs (); +        } + +out: +        return ret; +} + +int +glusterd_op_delete_volume (dict_t *dict) +{ +        int                                     ret = 0; +        char                                    *volname = NULL; +        glusterd_conf_t                         *priv = NULL; +        glusterd_volinfo_t                      *volinfo = NULL; +        xlator_t                                *this = NULL; + +        this = THIS; +        GF_ASSERT (this); +        priv = this->private; +        GF_ASSERT (priv); + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get volume name"); +                goto out; +        } + +        ret  = glusterd_volinfo_find (volname, &volinfo); + +        if (ret) +                goto out; + +        ret = glusterd_delete_volume (volinfo); +out: +        gf_log ("", GF_LOG_DEBUG, "returning %d", ret); +        return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index e16d6209b..5a39c3089 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -526,4 +526,57 @@ glusterd_rpc_create (struct rpc_clnt **rpc, dict_t *options,  int  glusterd_handle_log_level (rpcsvc_request_t *req); + +/* handler functions */ +int32_t glusterd_op_begin (rpcsvc_request_t *req, glusterd_op_t op, void *ctx); + +int glusterd_handle_gsync_set (rpcsvc_request_t *req); +int glusterd_handle_quota (rpcsvc_request_t *req); +int glusterd_handle_replace_brick (rpcsvc_request_t *req); +int glusterd_handle_log_filename (rpcsvc_request_t *req); +int glusterd_handle_log_locate (rpcsvc_request_t *req); +int glusterd_handle_log_level (rpcsvc_request_t *req); +int glusterd_handle_log_rotate (rpcsvc_request_t *req); +int glusterd_handle_create_volume (rpcsvc_request_t *req); +int glusterd_handle_cli_start_volume (rpcsvc_request_t *req); +int glusterd_handle_cli_stop_volume (rpcsvc_request_t *req); +int glusterd_handle_cli_delete_volume (rpcsvc_request_t *req); + + +/* op-sm functions */ +int glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr); +int glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict); +int glusterd_op_quota (dict_t *dict, char **op_errstr); +int glusterd_op_stage_quota (dict_t *dict, char **op_errstr); +int glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, +                                     dict_t *rsp_dict); +int glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict); +int glusterd_op_log_level (dict_t *dict); +int glusterd_op_log_filename (dict_t *dict); +int glusterd_op_log_rotate (dict_t *dict); +int glusterd_op_stage_log_level (dict_t *dict, char **op_errstr); +int glusterd_op_stage_log_filename (dict_t *dict, char **op_errstr); +int glusterd_op_stage_log_rotate (dict_t *dict, char **op_errstr); +int glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr); +int glusterd_op_stage_start_volume (dict_t *dict, char **op_errstr); +int glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr); +int glusterd_op_stage_delete_volume (dict_t *dict, char **op_errstr); +int glusterd_op_create_volume (dict_t *dict, char **op_errstr); +int glusterd_op_start_volume (dict_t *dict, char **op_errstr); +int glusterd_op_stop_volume (dict_t *dict); +int glusterd_op_delete_volume (dict_t *dict); + +int glusterd_op_add_brick (dict_t *dict, char **op_errstr); +int glusterd_op_remove_brick (dict_t *dict); +int glusterd_op_stage_add_brick (dict_t *dict, char **op_errstr); +int glusterd_op_stage_remove_brick (dict_t *dict); + + + +/* misc */ +void glusterd_do_replace_brick (void *data); +int glusterd_op_perform_remove_brick (glusterd_volinfo_t  *volinfo, char *brick); +int glusterd_op_stop_volume_args_get (dict_t *dict, char** volname, int *flags); + +  #endif  | 
