diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-utils.c')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 613 | 
1 files changed, 562 insertions, 51 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 5f9098f3e9d..5cad58cbb2e 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -93,6 +93,30 @@  #define NLMV4_VERSION       4  #define NLMV1_VERSION       1 +int +send_attach_req (xlator_t *this, struct rpc_clnt *rpc, char *path, int op); + +static gf_boolean_t +is_brick_mx_enabled () +{ +        char            *value = NULL; +        int             ret = 0; +        gf_boolean_t    enabled = _gf_false; +        xlator_t        *this = NULL; +        glusterd_conf_t *priv = NULL; + +        this = THIS; + +        priv = this->private; + +        ret = dict_get_str (priv->opts, GLUSTERD_BRICK_MULTIPLEX_KEY, &value); + +        if (!ret) +                ret = gf_string2boolean (value, &enabled); + +        return ret ? _gf_false: enabled; +} +  extern struct volopt_map_entry glusterd_volopt_map[];  extern glusterd_all_vol_opts valid_all_vol_opts[]; @@ -1690,8 +1714,6 @@ glusterd_set_brick_socket_filepath (glusterd_volinfo_t *volinfo,                                      glusterd_brickinfo_t *brickinfo,                                      char *sockpath, size_t len)  { -        char                    export_path[PATH_MAX] = {0,}; -        char                    sock_filepath[PATH_MAX] = {0,};          char                    volume_dir[PATH_MAX] = {0,};          xlator_t                *this = NULL;          glusterd_conf_t         *priv = NULL; @@ -1706,11 +1728,18 @@ glusterd_set_brick_socket_filepath (glusterd_volinfo_t *volinfo,          priv = this->private;          GLUSTERD_GET_VOLUME_DIR (volume_dir, volinfo, priv); -        GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, export_path); -        snprintf (sock_filepath, PATH_MAX, "%s/run/%s-%s", -                  volume_dir, brickinfo->hostname, export_path); +        if (is_brick_mx_enabled ()) { +                snprintf (sockpath, len, "%s/run/daemon-%s.socket", +                          volume_dir, brickinfo->hostname); +        } else { +                char                    export_path[PATH_MAX] = {0,}; +                char                    sock_filepath[PATH_MAX] = {0,}; +                GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, export_path); +                snprintf (sock_filepath, PATH_MAX, "%s/run/%s-%s", +                          volume_dir, brickinfo->hostname, export_path); -        glusterd_set_socket_filepath (sock_filepath, sockpath, len); +                glusterd_set_socket_filepath (sock_filepath, sockpath, len); +        }  }  /* connection happens only if it is not aleady connected, @@ -1749,7 +1778,7 @@ glusterd_brick_connect (glusterd_volinfo_t  *volinfo,                  ret = glusterd_rpc_create (&rpc, options,                                             glusterd_brick_rpc_notify, -                                           brickid); +                                           brickid, _gf_false);                  if (ret) {                          GF_FREE (brickid);                          goto out; @@ -1802,6 +1831,8 @@ glusterd_volume_start_glusterfs (glusterd_volinfo_t  *volinfo,          char                    glusterd_uuid[1024] = {0,};          char                    valgrind_logfile[PATH_MAX] = {0};          char                    rdma_brick_path[PATH_MAX] = {0,}; +        struct rpc_clnt         *rpc = NULL; +        rpc_clnt_connection_t   *conn  = NULL;          GF_ASSERT (volinfo);          GF_ASSERT (brickinfo); @@ -1823,16 +1854,33 @@ glusterd_volume_start_glusterfs (glusterd_volinfo_t  *volinfo,                  goto out;          } -        ret = _mk_rundir_p (volinfo); -        if (ret) -                goto out; +        GLUSTERD_GET_BRICK_PIDFILE (pidfile, volinfo, brickinfo, priv); +        if (gf_is_service_running (pidfile, NULL)) { +                goto connect; +        } +        /* +         * There are all sorts of races in the start/stop code that could leave +         * a UNIX-domain socket or RPC-client object associated with a +         * long-dead incarnation of this brick, while the new incarnation is +         * listening on a new socket at the same path and wondering why we +         * haven't shown up.  To avoid the whole mess and be on the safe side, +         * we just blow away anything that might have been left over, and start +         * over again. +         */          glusterd_set_brick_socket_filepath (volinfo, brickinfo, socketpath,                                              sizeof (socketpath)); - -        GLUSTERD_GET_BRICK_PIDFILE (pidfile, volinfo, brickinfo, priv); -        if (gf_is_service_running (pidfile, NULL)) -                goto connect; +        (void) glusterd_unlink_file (socketpath); +        rpc = brickinfo->rpc; +        if (rpc) { +                brickinfo->rpc = NULL; +                conn = &rpc->conn; +                if (conn->reconnect) { +                        (void ) gf_timer_call_cancel (rpc->ctx, conn->reconnect); +                        //rpc_clnt_unref (rpc); +                } +                rpc_clnt_unref (rpc); +        }          port = pmap_assign_port (THIS, brickinfo->port, brickinfo->path); @@ -1933,6 +1981,7 @@ retry:          brickinfo->port = port;          brickinfo->rdma_port = rdma_port; +        brickinfo->started_here = _gf_true;          if (wait) {                  synclock_unlock (&priv->big_lock); @@ -1978,6 +2027,7 @@ connect:                          brickinfo->hostname, brickinfo->path, socketpath);                  goto out;          } +  out:          return ret;  } @@ -2035,9 +2085,8 @@ glusterd_volume_stop_glusterfs (glusterd_volinfo_t  *volinfo,                                  gf_boolean_t del_brick)  {          xlator_t        *this                   = NULL; -        glusterd_conf_t *priv                   = NULL; -        char            pidfile[PATH_MAX]       = {0,};          int             ret                     = 0; +        char            *op_errstr              = NULL;          GF_ASSERT (volinfo);          GF_ASSERT (brickinfo); @@ -2045,18 +2094,32 @@ glusterd_volume_stop_glusterfs (glusterd_volinfo_t  *volinfo,          this = THIS;          GF_ASSERT (this); -        priv = this->private;          if (del_brick)                  cds_list_del_init (&brickinfo->brick_list);          if (GLUSTERD_STATUS_STARTED == volinfo->status) { -                (void) glusterd_brick_disconnect (brickinfo); -                GLUSTERD_GET_BRICK_PIDFILE (pidfile, volinfo, brickinfo, priv); -                ret = glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_false); -                if (ret == 0) { -                        glusterd_set_brick_status (brickinfo, GF_BRICK_STOPPED); -                        (void) glusterd_brick_unlink_socket_file (volinfo, brickinfo); +                /* +                 * In a post-multiplexing world, even if we're not actually +                 * doing any multiplexing, just dropping the RPC connection +                 * isn't enough.  There might be many such connections during +                 * the brick daemon's lifetime, even if we only consider the +                 * management RPC port (because tests etc. might be manually +                 * attaching and detaching bricks).  Therefore, we have to send +                 * an actual signal instead. +                 */ +                if (is_brick_mx_enabled ()) { +                        (void) send_attach_req (this, brickinfo->rpc, +                                                brickinfo->path, +                                                GLUSTERD_BRICK_TERMINATE); +                } else { +                        (void) glusterd_brick_terminate (volinfo, brickinfo, +                                                         NULL, 0, &op_errstr); +                        if (op_errstr) { +                                GF_FREE (op_errstr); +                        } +                        (void) glusterd_brick_disconnect (brickinfo);                  } +                ret = 0;          }          if (del_brick) @@ -4843,16 +4906,350 @@ out:          return ret;  } +static int32_t +my_callback (struct rpc_req *req, struct iovec *iov, int count, void *v_frame) +{ +        call_frame_t    *frame  = v_frame; + +        STACK_DESTROY (frame->root); + +        return 0; +} + +int +send_attach_req (xlator_t *this, struct rpc_clnt *rpc, char *path, int op) +{ +        int            ret      = -1; +        struct iobuf  *iobuf    = NULL; +        struct iobref *iobref   = NULL; +        struct iovec   iov      = {0, }; +        ssize_t        req_size = 0; +        call_frame_t  *frame    = NULL; +        gd1_mgmt_brick_op_req   brick_req; +        void                    *req = &brick_req; +        void          *errlbl   = &&err; +        extern struct rpc_clnt_program gd_brick_prog; + +        if (!rpc) { +                gf_log (this->name, GF_LOG_ERROR, "called with null rpc"); +                return -1; +        } + +        brick_req.op = op; +        brick_req.name = path; +        brick_req.input.input_val = NULL; +        brick_req.input.input_len = 0; + +        req_size = xdr_sizeof ((xdrproc_t)xdr_gd1_mgmt_brick_op_req, req); +        iobuf = iobuf_get2 (rpc->ctx->iobuf_pool, req_size); +        if (!iobuf) { +                goto *errlbl; +        } +        errlbl = &&maybe_free_iobuf; + +        iov.iov_base = iobuf->ptr; +        iov.iov_len  = iobuf_pagesize (iobuf); + +        iobref = iobref_new (); +        if (!iobref) { +                goto *errlbl; +        } +        errlbl = &&free_iobref; + +        frame = create_frame (this, this->ctx->pool); +        if (!frame) { +                goto *errlbl; +        } + +        iobref_add (iobref, iobuf); +        /* +         * Drop our reference to the iobuf.  The iobref should already have +         * one after iobref_add, so when we unref that we'll free the iobuf as +         * well.  This allows us to pass just the iobref as frame->local. +         */ +        iobuf_unref (iobuf); +        /* Set the pointer to null so we don't free it on a later error. */ +        iobuf = NULL; + +        /* Create the xdr payload */ +        ret = xdr_serialize_generic (iov, req, +                                     (xdrproc_t)xdr_gd1_mgmt_brick_op_req); +        if (ret == -1) { +                goto *errlbl; +        } + +        iov.iov_len = ret; + +        /* Send the msg */ +        ret = rpc_clnt_submit (rpc, &gd_brick_prog, op, +                               my_callback, &iov, 1, NULL, 0, iobref, frame, +                               NULL, 0, NULL, 0, NULL); +        return ret; + +free_iobref: +        iobref_unref (iobref); +maybe_free_iobuf: +        if (iobuf) { +                iobuf_unref (iobuf); +        } +err: +        return -1; +} + +extern size_t +build_volfile_path (char *volume_id, char *path, +                    size_t path_len, char *trusted_str); + + +static int +attach_brick (xlator_t *this, +              glusterd_brickinfo_t *brickinfo, +              glusterd_brickinfo_t *other_brick, +              glusterd_volinfo_t *volinfo, +              glusterd_volinfo_t *other_vol) +{ +        glusterd_conf_t *conf                   = this->private; +        char            pidfile1[PATH_MAX]      = {0}; +        char            pidfile2[PATH_MAX]      = {0}; +        char            unslashed[PATH_MAX]     = {'\0',}; +        char            full_id[PATH_MAX]       = {'\0',}; +        char            path[PATH_MAX]          = {'\0',}; +        int             ret; + +        gf_log (this->name, GF_LOG_INFO, +                "add brick %s to existing process for %s", +                brickinfo->path, other_brick->path); + +        GLUSTERD_REMOVE_SLASH_FROM_PATH (brickinfo->path, unslashed); + +        ret = pmap_registry_extend (this, other_brick->port, +                                    brickinfo->path); +        if (ret != 0) { +                gf_log (this->name, GF_LOG_ERROR, +                        "adding brick to process failed"); +                return -1; +        } + +        brickinfo->port = other_brick->port; +        brickinfo->status = GF_BRICK_STARTED; +        brickinfo->started_here = _gf_true; +        brickinfo->rpc = rpc_clnt_ref (other_brick->rpc); + +        GLUSTERD_GET_BRICK_PIDFILE (pidfile1, other_vol, other_brick, conf); +        GLUSTERD_GET_BRICK_PIDFILE (pidfile2, volinfo, brickinfo, conf); +        (void) sys_unlink (pidfile2); +        (void) sys_link (pidfile1, pidfile2); + +        if (volinfo->is_snap_volume) { +                snprintf (full_id, sizeof(full_id), "/%s/%s/%s.%s.%s", +                          GLUSTERD_VOL_SNAP_DIR_PREFIX, +                          volinfo->snapshot->snapname, +                          volinfo->volname, brickinfo->hostname, unslashed); +        } else { +                snprintf (full_id, sizeof(full_id), "%s.%s.%s", +                          volinfo->volname, brickinfo->hostname, unslashed); +        } +        (void) build_volfile_path (full_id, path, sizeof(path), NULL); + +        int tries = 0; +        while (tries++ <= 10) { +                ret = send_attach_req (this, other_brick->rpc, path, +                                       GLUSTERD_BRICK_ATTACH); +                if (!ret) { +                        return 0; +                } +                /* +                 * It might not actually be safe to manipulate the lock like +                 * this, but if we don't then the connection can never actually +                 * complete and retries are useless.  Unfortunately, all of the +                 * alternatives (e.g. doing all of this in a separate thread) +                 * are much more complicated and risky.  TBD: see if there's a +                 * better way +                 */ +                synclock_unlock (&conf->big_lock); +                sleep (1); +                synclock_lock (&conf->big_lock); +        } + +        gf_log (this->name, GF_LOG_WARNING, +                "attach failed for %s", brickinfo->path); +        return ret; +} + +static glusterd_brickinfo_t * +find_compatible_brick_in_volume (glusterd_conf_t *conf, +                                 glusterd_volinfo_t *volinfo, +                                 glusterd_brickinfo_t *brickinfo) +{ +        xlator_t                *this                   = THIS; +        glusterd_brickinfo_t    *other_brick; +        char                    pidfile2[PATH_MAX]      = {0}; +        int32_t                 pid2                    = -1; + +        cds_list_for_each_entry (other_brick, &volinfo->bricks, +                                 brick_list) { +                if (other_brick == brickinfo) { +                        continue; +                } +                if (!other_brick->started_here) { +                        continue; +                } +                if (strcmp (brickinfo->hostname, other_brick->hostname) != 0) { +                        continue; +                } +                GLUSTERD_GET_BRICK_PIDFILE (pidfile2, volinfo, other_brick, +                                            conf); +                if (!gf_is_service_running (pidfile2, &pid2)) { +                        gf_log (this->name, GF_LOG_INFO, +                                "cleaning up dead brick %s:%s", +                                other_brick->hostname, other_brick->path); +                        other_brick->started_here = _gf_false; +                        sys_unlink (pidfile2); +                        continue; +                } +                return other_brick; +        } + +        return NULL; +} + +static gf_boolean_t +unsafe_option (dict_t *this, char *key, data_t *value, void *arg) +{ +        /* +         * Certain options are safe because they're already being handled other +         * ways, such as being copied down to the bricks (all auth options) or +         * being made irrelevant (event-threads).  All others are suspect and +         * must be checked in the next function. +         */ +        if (fnmatch ("*auth*", key, 0) == 0) { +                return _gf_false; +        } + +        if (fnmatch ("*event-threads", key, 0) == 0) { +                return _gf_false; +        } + +        return _gf_true; +} + +static int +opts_mismatch (dict_t *dict1, char *key, data_t *value1, void *dict2) +{ +        data_t  *value2         = dict_get (dict2, key); +        int32_t min_len; + +        /* +         * If the option is only present on one, we can either look at the +         * default or assume a mismatch.  Looking at the default is pretty +         * hard, because that's part of a structure within each translator and +         * there's no dlopen interface to get at it, so we assume a mismatch. +         * If the user really wants them to match (and for their bricks to be +         * multiplexed, they can always reset the option). +         */ +        if (!value2) { +                gf_log (THIS->name, GF_LOG_DEBUG, "missing option %s", key); +                return -1; +        } + +        min_len = MIN (value1->len, value2->len); +        if (strncmp (value1->data, value2->data, min_len) != 0) { +                gf_log (THIS->name, GF_LOG_DEBUG, +                        "option mismatch, %s, %s != %s", +                        key, value1->data, value2->data); +                return -1; +        } + +        return 0; +} + +static glusterd_brickinfo_t * +find_compatible_brick (glusterd_conf_t *conf, +                       glusterd_volinfo_t *volinfo, +                       glusterd_brickinfo_t *brickinfo, +                       glusterd_volinfo_t **other_vol_p) +{ +        glusterd_brickinfo_t    *other_brick; +        glusterd_volinfo_t      *other_vol; + +        /* Just return NULL here if multiplexing is disabled. */ +        if (!is_brick_mx_enabled ()) { +                return NULL; +        } + +        other_brick = find_compatible_brick_in_volume (conf, volinfo, +                                                       brickinfo); +        if (other_brick) { +                *other_vol_p = volinfo; +                return other_brick; +        } + +        cds_list_for_each_entry (other_vol, &conf->volumes, vol_list) { +                if (other_vol == volinfo) { +                        continue; +                } +                if (volinfo->is_snap_volume) { +                        /* +                         * Snap volumes do have different options than their +                         * parents, but are nonetheless generally compatible. +                         * Skip the option comparison for now, until we figure +                         * out how to handle this (e.g. compare at the brick +                         * level instead of the volume level for this case). +                         * +                         * TBD: figure out compatibility for snap bricks +                         */ +                        goto no_opt_compare; +                } +                /* +                 * It's kind of a shame that we have to do this check in both +                 * directions, but an option might only exist on one of the two +                 * dictionaries and dict_foreach_match will only find that one. +                 */ +                gf_log (THIS->name, GF_LOG_DEBUG, +                        "comparing options for %s and %s", +                        volinfo->volname, other_vol->volname); +                if (dict_foreach_match (volinfo->dict, unsafe_option, NULL, +                                        opts_mismatch, other_vol->dict) < 0) { +                        gf_log (THIS->name, GF_LOG_DEBUG, "failure forward"); +                        continue; +                } +                if (dict_foreach_match (other_vol->dict, unsafe_option, NULL, +                                        opts_mismatch, volinfo->dict) < 0) { +                        gf_log (THIS->name, GF_LOG_DEBUG, "failure backward"); +                        continue; +                } +                gf_log (THIS->name, GF_LOG_DEBUG, "all options match"); +no_opt_compare: +                other_brick = find_compatible_brick_in_volume (conf, +                                                               other_vol, +                                                               brickinfo); +                if (other_brick) { +                        *other_vol_p = other_vol; +                        return other_brick; +                } +        } + +        return NULL; +} +  int  glusterd_brick_start (glusterd_volinfo_t *volinfo,                        glusterd_brickinfo_t *brickinfo,                        gf_boolean_t wait)  { -        int                                     ret   = -1; -        xlator_t                                *this = NULL; +        int                     ret   = -1; +        xlator_t                *this = NULL; +        glusterd_brickinfo_t    *other_brick; +        glusterd_conf_t         *conf = NULL; +        int32_t                 pid                   = -1; +        char                    pidfile[PATH_MAX]     = {0}; +        FILE                    *fp; +        char                    socketpath[PATH_MAX]  = {0}; +        glusterd_volinfo_t      *other_vol;          this = THIS;          GF_ASSERT (this); +        conf = this->private;          if ((!brickinfo) || (!volinfo))                  goto out; @@ -4876,6 +5273,77 @@ glusterd_brick_start (glusterd_volinfo_t *volinfo,                  ret = 0;                  goto out;          } + +        GLUSTERD_GET_BRICK_PIDFILE (pidfile, volinfo, brickinfo, conf); +        if (gf_is_service_running (pidfile, &pid)) { +                /* +                 * In general, if the pidfile exists and points to a running +                 * process, this will already be set.  However, that's not the +                 * case when we're starting up and bricks are already running. +                 */ +                if (brickinfo->status != GF_BRICK_STARTED) { +                        gf_log (this->name, GF_LOG_INFO, +                                "discovered already-running brick %s", +                                brickinfo->path); +                        //brickinfo->status = GF_BRICK_STARTED; +                        (void) pmap_registry_bind (this, +                                        brickinfo->port, brickinfo->path, +                                        GF_PMAP_PORT_BRICKSERVER, NULL); +                        /* +                         * This will unfortunately result in a separate RPC +                         * connection per brick, even though they're all in +                         * the same process.  It works, but it would be nicer +                         * if we could find a pre-existing connection to that +                         * same port (on another brick) and re-use that. +                         * TBD: re-use RPC connection across bricks +                         */ +                        glusterd_set_brick_socket_filepath (volinfo, brickinfo, +                                        socketpath, sizeof (socketpath)); +                        (void) glusterd_brick_connect (volinfo, brickinfo, +                                        socketpath); +                } +                return 0; +        } + +        ret = _mk_rundir_p (volinfo); +        if (ret) +                goto out; + +        other_brick = find_compatible_brick (conf, volinfo, brickinfo, +                                             &other_vol); +        if (other_brick) { +                ret = attach_brick (this, brickinfo, other_brick, +                                    volinfo, other_vol); +                if (ret == 0) { +                        goto out; +                } +        } + +        /* +         * This hack is necessary because our brick-process management is a +         * total nightmare.  We expect a brick process's socket and pid files +         * to be ready *immediately* after we start it.  Ditto for it calling +         * back to bind its port.  Unfortunately, none of that is realistic. +         * Any process takes non-zero time to start up.  This has *always* been +         * racy and unsafe; it just became more visible with multiplexing. +         * +         * The right fix would be to do all of this setup *in the parent*, +         * which would include (among other things) getting the PID back from +         * the "runner" code.  That's all prohibitively difficult and risky. +         * To work around the more immediate problems, we create a stub pidfile +         * here to let gf_is_service_running know that we expect the process to +         * be there shortly, and then it gets filled in with a real PID when +         * the process does finish starting up. +         * +         * TBD: pray for GlusterD 2 to be ready soon. +         */ +        (void) sys_unlink (pidfile); +        fp = fopen (pidfile, "w+"); +        if (fp) { +                (void) fprintf (fp, "0\n"); +                (void) fclose (fp); +        } +          ret = glusterd_volume_start_glusterfs (volinfo, brickinfo, wait);          if (ret) {                  gf_msg (this->name, GF_LOG_ERROR, 0, @@ -5813,11 +6281,12 @@ glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo,          if (ret)                  goto out; -          GLUSTERD_GET_BRICK_PIDFILE (pidfile, volinfo, brickinfo, priv);          if (glusterd_is_brick_started (brickinfo)) { -                brick_online = gf_is_service_running (pidfile, &pid); +                if (gf_is_service_running (pidfile, &pid)) { +                        brick_online = _gf_true; +                }          }          memset (key, 0, sizeof (key)); @@ -6880,10 +7349,12 @@ out:          return ret;  } -int -glusterd_brick_statedump (glusterd_volinfo_t *volinfo, -                          glusterd_brickinfo_t *brickinfo, -                          char *options, int option_cnt, char **op_errstr) + +static int +glusterd_brick_signal (glusterd_volinfo_t *volinfo, +                       glusterd_brickinfo_t *brickinfo, +                       char *options, int option_cnt, char **op_errstr, +                       int sig)  {          int                     ret = -1;          xlator_t                *this = NULL; @@ -6916,6 +7387,7 @@ glusterd_brick_statedump (glusterd_volinfo_t *volinfo,          GLUSTERD_GET_BRICK_PIDFILE (pidfile_path, volinfo, brickinfo, conf); +        /* TBD: use gf_is_service_running instead of almost-identical code? */          pidfile = fopen (pidfile_path, "r");          if (!pidfile) {                  gf_msg ("glusterd", GF_LOG_ERROR, errno, @@ -6934,24 +7406,35 @@ glusterd_brick_statedump (glusterd_volinfo_t *volinfo,                  goto out;          } -        snprintf (dumpoptions_path, sizeof (dumpoptions_path), -                  DEFAULT_VAR_RUN_DIRECTORY"/glusterdump.%d.options", pid); -        ret = glusterd_set_dump_options (dumpoptions_path, options, option_cnt); -        if (ret < 0) { -                gf_msg ("glusterd", GF_LOG_ERROR, 0, -                       GD_MSG_BRK_STATEDUMP_FAIL, -                       "error while parsing the statedump " -                        "options"); -                ret = -1; +        if (pid == 0) { +                gf_msg ("glusterd", GF_LOG_WARNING, 0, +                        GD_MSG_NO_SIG_TO_PID_ZERO, +                        "refusing to send signal %d to pid zero", sig);                  goto out;          } +        if (sig == SIGUSR1) { +                snprintf (dumpoptions_path, sizeof (dumpoptions_path), +                          DEFAULT_VAR_RUN_DIRECTORY"/glusterdump.%d.options", +                          pid); +                ret = glusterd_set_dump_options (dumpoptions_path, options, +                                                 option_cnt); +                if (ret < 0) { +                        gf_msg ("glusterd", GF_LOG_ERROR, 0, +                               GD_MSG_BRK_STATEDUMP_FAIL, +                               "error while parsing the statedump " +                                "options"); +                        ret = -1; +                        goto out; +                } +        } +          gf_msg ("glusterd", GF_LOG_INFO, 0,                  GD_MSG_STATEDUMP_INFO, -                "Performing statedump on brick with pid %d", -                pid); +                "sending signal %d to brick with pid %d", +                sig, pid); -        kill (pid, SIGUSR1); +        kill (pid, sig);          sleep (1);          ret = 0; @@ -6963,6 +7446,26 @@ out:  }  int +glusterd_brick_statedump (glusterd_volinfo_t *volinfo, +                          glusterd_brickinfo_t *brickinfo, +                          char *options, int option_cnt, char **op_errstr) +{ +        return glusterd_brick_signal (volinfo, brickinfo, +                                      options, option_cnt, op_errstr, +                                      SIGUSR1); +} + +int +glusterd_brick_terminate (glusterd_volinfo_t *volinfo, +                          glusterd_brickinfo_t *brickinfo, +                          char *options, int option_cnt, char **op_errstr) +{ +        return glusterd_brick_signal (volinfo, brickinfo, +                                      options, option_cnt, op_errstr, +                                      SIGTERM); +} + +int  glusterd_nfs_statedump (char *options, int option_cnt, char **op_errstr)  {          int                     ret = -1; @@ -7446,7 +7949,7 @@ glusterd_volume_defrag_restart (glusterd_volinfo_t *volinfo, char *op_errstr,                                            "volume=%s", volinfo->volname);                                  goto out;                          } -                        ret = glusterd_rebalance_rpc_create (volinfo, _gf_true); +                        ret = glusterd_rebalance_rpc_create (volinfo);                          break;                  }          case GF_DEFRAG_STATUS_NOT_STARTED: @@ -7978,9 +8481,10 @@ glusterd_to_cli (rpcsvc_request_t *req, gf_cli_rsp *arg, struct iovec *payload,          glusterd_submit_reply (req, arg, payload, payloadcount, iobref,                                 (xdrproc_t) xdrproc); -        if (dict) -                dict_unref (dict); +        if (dict) { +                dict_unref (dict); +        }          return ret;  } @@ -11356,6 +11860,7 @@ glusterd_get_global_options_for_all_vols (rpcsvc_request_t *req, dict_t *ctx,          char                    *allvolopt = NULL;          int32_t                 i = 0;          gf_boolean_t            exists = _gf_false; +        gf_boolean_t            need_free;          this = THIS;          GF_VALIDATE_OR_GOTO (THIS->name, this, out); @@ -11414,13 +11919,16 @@ glusterd_get_global_options_for_all_vols (rpcsvc_request_t *req, dict_t *ctx,                  ret = dict_get_str (priv->opts, allvolopt, &def_val);                  /* If global option isn't set explicitly */ + +                need_free = _gf_false;                  if (!def_val) { -                        if (!strcmp (allvolopt, GLUSTERD_GLOBAL_OP_VERSION_KEY)) +                        if (!strcmp (allvolopt, +                                     GLUSTERD_GLOBAL_OP_VERSION_KEY)) {                                  gf_asprintf (&def_val, "%d", priv->op_version); -                        else if (!strcmp (allvolopt, GLUSTERD_QUORUM_RATIO_KEY)) -                                gf_asprintf (&def_val, "%d", 0); -                        else if (!strcmp (allvolopt, GLUSTERD_SHARED_STORAGE_KEY)) -                                gf_asprintf (&def_val, "%s", "disable"); +                                need_free = _gf_true; +                        } else { +                                def_val = valid_all_vol_opts[i].dflt_val; +                        }                  }                  count++; @@ -11443,6 +11951,9 @@ glusterd_get_global_options_for_all_vols (rpcsvc_request_t *req, dict_t *ctx,                          goto out;                  } +                if (need_free) { +                        GF_FREE (def_val); +                }                  def_val = NULL;                  allvolopt = NULL;  | 
