summaryrefslogtreecommitdiffstats
path: root/xlators/mgmt/glusterd/src/glusterd-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'xlators/mgmt/glusterd/src/glusterd-utils.c')
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c613
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;