summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli/src/cli-cmd-parser.c55
-rw-r--r--cli/src/cli-cmd-volume.c70
-rw-r--r--cli/src/cli-rpc-ops.c72
-rw-r--r--cli/src/cli.h4
-rw-r--r--libglusterfs/src/common-utils.c18
-rw-r--r--libglusterfs/src/common-utils.h13
-rw-r--r--libglusterfs/src/glusterfs.h1
-rw-r--r--libglusterfs/src/statedump.c112
-rw-r--r--libglusterfs/src/statedump.h5
-rw-r--r--rpc/rpc-lib/src/protocol-common.h1
-rw-r--r--rpc/xdr/src/cli1-xdr.c34
-rw-r--r--rpc/xdr/src/cli1-xdr.h23
-rw-r--r--rpc/xdr/src/cli1-xdr.x15
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-handler.c4
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-op-sm.c35
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-rpc-ops.c14
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c109
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h5
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.c1
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-ops.c161
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.h20
-rw-r--r--xlators/protocol/server/src/server.c45
22 files changed, 732 insertions, 85 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index 6d984680e35..d3cb1240fe7 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -1731,3 +1731,58 @@ cli_cmd_volume_status_parse (const char **words, int wordcount,
return ret;
}
+
+gf_boolean_t
+cli_cmd_validate_dumpoption (const char *option)
+{
+ char *opwords[] = {"all", "mem", "iobuf", "callpool", "priv", "fd",
+ "inode", NULL};
+ char *w = NULL;
+
+ w = str_getunamb (option, opwords);
+ if (!w) {
+ gf_log ("cli", GF_LOG_DEBUG, "Unknown statedump option %s",
+ option);
+ return _gf_false;
+ }
+ return _gf_true;
+}
+
+int
+cli_cmd_volume_statedump_options_parse (const char **words, int wordcount,
+ dict_t **options)
+{
+ int ret = 0;
+ int i = 0;
+ dict_t *dict = NULL;
+ int option_cnt = 0;
+ char option_str[100] = {0,};
+
+ for (i = 3; i < wordcount; i++, option_cnt++) {
+ if (!cli_cmd_validate_dumpoption (words[i])) {
+ ret = -1;
+ goto out;
+ }
+ strncat (option_str, words[i], sizeof (words [i]));
+ strncat (option_str, " ", 1);
+ }
+ dict = dict_new ();
+ if (!dict)
+ goto out;
+
+ ret = dict_set_str (dict, "options", gf_strdup (option_str));
+ if (ret)
+ goto out;
+
+ ret = dict_set_int32 (dict, "option-cnt", option_cnt);
+ if (ret)
+ goto out;
+
+ *options = dict;
+out:
+ if (ret && dict)
+ dict_destroy (dict);
+ if (ret)
+ gf_log ("cli", GF_LOG_ERROR, "Error parsing dumpoptions");
+ return ret;
+}
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c
index 00077253237..9b85bf819c1 100644
--- a/cli/src/cli-cmd-volume.c
+++ b/cli/src/cli-cmd-volume.c
@@ -1510,6 +1510,72 @@ out:
return ret;
}
+int
+cli_cmd_volume_statedump_cbk (struct cli_state *state, struct cli_cmd_word *word,
+ const char **words, int wordcount)
+{
+ int ret = -1;
+ rpc_clnt_procedure_t *proc = NULL;
+ call_frame_t *frame = NULL;
+ dict_t *options = NULL;
+ int sent = 0;
+ int parse_error = 0;
+
+ frame = create_frame (THIS, THIS->ctx->pool);
+ if (!frame)
+ goto out;
+
+ if (wordcount < 3) {
+ cli_usage_out (word->pattern);
+ parse_error = 1;
+ goto out;
+ }
+
+ if (wordcount > 3) {
+ ret = cli_cmd_volume_statedump_options_parse (words, wordcount,
+ &options);
+ if (ret) {
+ parse_error = 1;
+ gf_log ("cli", GF_LOG_ERROR, "Error parsing "
+ "statedump options");
+ cli_out ("Error parsing options");
+ cli_usage_out (word->pattern);
+ }
+ } else {
+ options = dict_new ();
+ if (!options) {
+ ret = -1;
+ gf_log ("cli", GF_LOG_ERROR, "Could not create dict");
+ goto out;
+ }
+ ret = dict_set_str (options, "options","");
+ if (ret)
+ goto out;
+ ret = dict_set_int32 (options, "option-cnt", 0);
+ if (ret)
+ goto out;
+ }
+
+ ret = dict_set_str (options, "volname", (char *)words[2]);
+ if (ret)
+ goto out;
+
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATEDUMP_VOLUME];
+ if (proc->fn) {
+ ret = proc->fn (frame, THIS, options);
+ }
+
+out:
+ if (ret) {
+ cli_cmd_sent_status_get (&sent);
+ if ((sent == 0) && (parse_error = 0))
+ cli_out ("Volume statedump failed");
+ }
+
+ return ret;
+}
+
+
struct cli_cmd volume_cmds[] = {
{ "volume info [all|<VOLNAME>]",
cli_cmd_volume_info_cbk,
@@ -1616,6 +1682,10 @@ struct cli_cmd volume_cmds[] = {
cli_cmd_volume_heal_cbk,
"Start healing of volume specified by <VOLNAME>"},
+ {"volume statedump <VOLNAME> [all|mem|iobuf|callpool|priv|fd|inode]...",
+ cli_cmd_volume_statedump_cbk,
+ "perform statedump on bricks"},
+
{ NULL, NULL, NULL }
};
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
index b58e0317363..1e77ae0ab71 100644
--- a/cli/src/cli-rpc-ops.c
+++ b/cli/src/cli-rpc-ops.c
@@ -4000,7 +4000,76 @@ out:
return ret;
}
+int32_t
+gf_cli3_1_statedump_volume_cbk (struct rpc_req *req, struct iovec *iov,
+ int count, void *myframe)
+{
+ gf1_cli_statedump_vol_rsp rsp = {0,};
+ int ret = -1;
+
+ if (-1 == req->rpc_status)
+ goto out;
+ ret = xdr_to_generic (*iov, &rsp,
+ (xdrproc_t)xdr_gf1_cli_statedump_vol_rsp);
+ if (ret < 0) {
+ gf_log (THIS->name, GF_LOG_ERROR, "XDR decoding failed");
+ goto out;
+ }
+ gf_log ("cli", GF_LOG_DEBUG, "Recieved response to statedump");
+ if (rsp.op_ret)
+ cli_out ("%s", rsp.op_errstr);
+ else
+ cli_out ("Volume statedump sucessful");
+
+ ret = rsp.op_ret;
+
+out:
+ cli_cmd_broadcast_response (ret);
+ return ret;
+}
+
+int32_t
+gf_cli3_1_statedump_volume (call_frame_t *frame, xlator_t *this,
+ void *data)
+{
+ gf1_cli_statedump_vol_req req = {0,};
+ dict_t *options = NULL;
+ char *volname = NULL;
+ char *option_str = NULL;
+ int option_cnt = 0;
+ int ret = -1;
+
+ if (!frame || !this || !data)
+ goto out;
+
+ options = data;
+
+ ret = dict_get_str (options, "volname", &volname);
+ if (ret)
+ goto out;
+ req.volname = volname;
+
+ ret = dict_get_str (options, "options", &option_str);
+ if (ret)
+ goto out;
+ req.options = option_str;
+
+ ret = dict_get_int32 (options, "option-cnt", &option_cnt);
+ if (ret)
+ goto out;
+ req.option_cnt = option_cnt;
+ ret = cli_cmd_submit (&req, frame, cli_rpc_prog,
+ GLUSTER_CLI_STATEDUMP_VOLUME, NULL,
+ this, gf_cli3_1_statedump_volume_cbk,
+ (xdrproc_t)xdr_gf1_cli_statedump_vol_req);
+
+out:
+ if (options)
+ dict_destroy (options);
+ gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
+ return ret;
+}
struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {
[GLUSTER_CLI_NULL] = {"NULL", NULL },
@@ -4036,7 +4105,8 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {
[GLUSTER_CLI_STATUS_VOLUME] = {"STATUS_VOLUME", gf_cli3_1_status_volume},
[GLUSTER_CLI_MOUNT] = {"MOUNT", gf_cli3_1_mount},
[GLUSTER_CLI_UMOUNT] = {"UMOUNT", gf_cli3_1_umount},
- [GLUSTER_CLI_HEAL_VOLUME] = {"HEAL_VOLUME", gf_cli3_1_heal_volume}
+ [GLUSTER_CLI_HEAL_VOLUME] = {"HEAL_VOLUME", gf_cli3_1_heal_volume},
+ [GLUSTER_CLI_STATEDUMP_VOLUME] = {"STATEDUMP_VOLUME", gf_cli3_1_statedump_volume},
};
struct rpc_clnt_program cli_prog = {
diff --git a/cli/src/cli.h b/cli/src/cli.h
index 4ef1dbe06f6..0a2fdb54b07 100644
--- a/cli/src/cli.h
+++ b/cli/src/cli.h
@@ -230,6 +230,10 @@ cli_cmd_log_locate_parse (const char **words, int wordcount, dict_t **options);
int32_t
cli_cmd_log_filename_parse (const char **words, int wordcount, dict_t **options);
+int32_t
+cli_cmd_volume_statedump_options_parse (const char **words, int wordcount,
+ dict_t **options);
+
cli_local_t * cli_local_get ();
void
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c
index 6ee32cac747..b2e91608b7a 100644
--- a/libglusterfs/src/common-utils.c
+++ b/libglusterfs/src/common-utils.c
@@ -1877,4 +1877,22 @@ get_path_name (char *word, char **path)
return *path;
}
+void
+gf_path_strip_trailing_slashes (char *path)
+{
+ int i = 0;
+ int len = 0;
+ if (!path)
+ return;
+
+ len = strlen (path);
+ for (i = len - 1; i > 0; i--)
+ if (path[i] != '/')
+ break;
+
+ if (i < (len -1))
+ path [i+1] = '\0';
+
+ return;
+}
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h
index c7d784ca8f7..82e499b392a 100644
--- a/libglusterfs/src/common-utils.h
+++ b/libglusterfs/src/common-utils.h
@@ -133,6 +133,18 @@ extern char *gf_mgmt_list[GF_MGMT_MAXVALUE];
} \
} while (0);
+#define GF_REMOVE_SLASH_FROM_PATH(path, string) \
+ do { \
+ int i = 0; \
+ for (i = 1; i < strlen (path); i++) { \
+ string[i-1] = path[i]; \
+ if (string[i-1] == '/') \
+ string[i-1] = '-'; \
+ } \
+ } while (0); \
+
+
+
#define GF_FILE_CONTENT_REQUESTED(_xattr_req,_content_limit) \
(dict_get_uint64 (_xattr_req, "glusterfs.content", _content_limit) == 0)
@@ -386,4 +398,5 @@ char *gf_uint64_2human_readable (uint64_t);
int validate_brick_name (char *brick);
char *get_host_name (char *word, char **host);
char *get_path_name (char *word, char **path);
+void gf_path_strip_trailing_slashes (char *path);
#endif /* _COMMON_UTILS_H */
diff --git a/libglusterfs/src/glusterfs.h b/libglusterfs/src/glusterfs.h
index 8247c60fbf6..57a542bb35a 100644
--- a/libglusterfs/src/glusterfs.h
+++ b/libglusterfs/src/glusterfs.h
@@ -352,6 +352,7 @@ struct _glusterfs_ctx {
struct list_head mempool_list; /* used to keep a global list of
mempools, used to log details of
mempool in statedump */
+ char *statedump_path;
};
typedef struct _glusterfs_ctx glusterfs_ctx_t;
diff --git a/libglusterfs/src/statedump.c b/libglusterfs/src/statedump.c
index cf947996b6b..525980bfacd 100644
--- a/libglusterfs/src/statedump.c
+++ b/libglusterfs/src/statedump.c
@@ -23,6 +23,7 @@
#include "iobuf.h"
#include "statedump.h"
#include "stack.h"
+#include "common-utils.h"
#ifdef HAVE_MALLOC_H
#include <malloc.h>
@@ -62,13 +63,13 @@ gf_proc_dump_unlock (void)
static int
-gf_proc_dump_open (void)
+gf_proc_dump_open (char *dump_dir, char *brickname)
{
- char path[256];
+ char path[PATH_MAX] = {0,};
int dump_fd = -1;
- memset (path, 0, sizeof (path));
- snprintf (path, sizeof (path), "%s.%d", GF_DUMP_LOGFILE_ROOT, getpid ());
+ snprintf (path, sizeof (path), "%s/%s.%d.dump", (dump_dir ?
+ dump_dir : "/tmp"), brickname, getpid());
dump_fd = open (path, O_CREAT|O_RDWR|O_TRUNC|O_APPEND, 0600);
if (dump_fd < 0)
@@ -356,6 +357,41 @@ gf_proc_dump_oldgraph_xlator_info (xlator_t *top)
}
static int
+gf_proc_dump_enable_all_options ()
+{
+
+ GF_PROC_DUMP_SET_OPTION (dump_options.dump_mem, _gf_true);
+ GF_PROC_DUMP_SET_OPTION (dump_options.dump_iobuf, _gf_true);
+ GF_PROC_DUMP_SET_OPTION (dump_options.dump_callpool, _gf_true);
+ GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_priv, _gf_true);
+ GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inode, _gf_true);
+ GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fd, _gf_true);
+ GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inodectx,
+ _gf_true);
+ GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fdctx, _gf_true);
+
+ return 0;
+}
+
+static int
+gf_proc_dump_disable_all_options ()
+{
+
+ GF_PROC_DUMP_SET_OPTION (dump_options.dump_mem, _gf_false);
+ GF_PROC_DUMP_SET_OPTION (dump_options.dump_iobuf, _gf_false);
+ GF_PROC_DUMP_SET_OPTION (dump_options.dump_callpool, _gf_false);
+ GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_priv, _gf_false);
+ GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inode,
+ _gf_false);
+ GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fd, _gf_false);
+ GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inodectx,
+ _gf_false);
+ GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fdctx, _gf_false);
+
+ return 0;
+}
+
+static int
gf_proc_dump_parse_set_option (char *key, char *value)
{
gf_boolean_t *opt_key = NULL;
@@ -363,7 +399,10 @@ gf_proc_dump_parse_set_option (char *key, char *value)
char buf[GF_DUMP_MAX_BUF_LEN];
int ret = -1;
- if (!strncasecmp (key, "mem", 3)) {
+ if (!strncasecmp (key, "all", 3)) {
+ (void)gf_proc_dump_enable_all_options ();
+ return 0;
+ } else if (!strncasecmp (key, "mem", 3)) {
opt_key = &dump_options.dump_mem;
} else if (!strncasecmp (key, "iobuf", 5)) {
opt_key = &dump_options.dump_iobuf;
@@ -398,44 +437,8 @@ gf_proc_dump_parse_set_option (char *key, char *value)
return 0;
}
-
static int
-gf_proc_dump_enable_all_options ()
-{
-
- GF_PROC_DUMP_SET_OPTION (dump_options.dump_mem, _gf_true);
- GF_PROC_DUMP_SET_OPTION (dump_options.dump_iobuf, _gf_true);
- GF_PROC_DUMP_SET_OPTION (dump_options.dump_callpool, _gf_true);
- GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_priv, _gf_true);
- GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inode, _gf_true);
- GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fd, _gf_true);
- GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inodectx,
- _gf_true);
- GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fdctx, _gf_true);
-
- return 0;
-}
-
-static int
-gf_proc_dump_disable_all_options ()
-{
-
- GF_PROC_DUMP_SET_OPTION (dump_options.dump_mem, _gf_false);
- GF_PROC_DUMP_SET_OPTION (dump_options.dump_iobuf, _gf_false);
- GF_PROC_DUMP_SET_OPTION (dump_options.dump_callpool, _gf_false);
- GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_priv, _gf_false);
- GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inode,
- _gf_false);
- GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fd, _gf_false);
- GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_inodectx,
- _gf_false);
- GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_fdctx, _gf_false);
-
- return 0;
-}
-
-static int
-gf_proc_dump_options_init ()
+gf_proc_dump_options_init (char *dump_name)
{
int ret = -1;
FILE *fp = NULL;
@@ -443,9 +446,12 @@ gf_proc_dump_options_init ()
char dumpbuf[GF_DUMP_MAX_BUF_LEN];
char *key = NULL, *value = NULL;
char *saveptr = NULL;
+ char dump_option_file[PATH_MAX];
+ snprintf (dump_option_file, sizeof (dump_option_file),
+ "/tmp/glusterdump.%d.options", getpid ());
- fp = fopen (GF_DUMP_OPTIONFILE, "r");
+ fp = fopen (dump_option_file, "r");
if (!fp) {
//ENOENT, return success
@@ -489,19 +495,26 @@ gf_proc_dump_info (int signum)
int ret = -1;
glusterfs_ctx_t *ctx = NULL;
glusterfs_graph_t *trav = NULL;
+ char brick_name[PATH_MAX] = {0,};
gf_proc_dump_lock ();
- ret = gf_proc_dump_open ();
- if (ret < 0)
+
+ ctx = glusterfs_ctx_get ();
+ if (!ctx)
goto out;
- ret = gf_proc_dump_options_init ();
+ if (ctx->cmd_args.brick_name) {
+ GF_REMOVE_SLASH_FROM_PATH (ctx->cmd_args.brick_name, brick_name);
+ } else
+ strncpy (brick_name, "glusterdump", sizeof (brick_name));
+
+ ret = gf_proc_dump_options_init (brick_name);
if (ret < 0)
goto out;
- ctx = glusterfs_ctx_get ();
- if (!ctx)
- goto close;
+ ret = gf_proc_dump_open (ctx->statedump_path, brick_name);
+ if (ret < 0)
+ goto out;
if (GF_PROC_DUMP_IS_OPTION_ENABLED (mem)) {
gf_proc_dump_mem_info ();
@@ -534,7 +547,6 @@ gf_proc_dump_info (int signum)
i++;
}
-close:
gf_proc_dump_close ();
out:
gf_proc_dump_unlock ();
diff --git a/libglusterfs/src/statedump.h b/libglusterfs/src/statedump.h
index 43330b37c36..fb07f5927a2 100644
--- a/libglusterfs/src/statedump.h
+++ b/libglusterfs/src/statedump.h
@@ -26,11 +26,6 @@
#define GF_DUMP_MAX_BUF_LEN 4096
-#define GF_DUMP_LOGFILE_ROOT "/tmp/glusterdump"
-#define GF_DUMP_LOGFILE_ROOT_LEN 256
-
-#define GF_DUMP_OPTIONFILE "/tmp/glusterdump.input"
-
typedef struct gf_dump_xl_options_ {
gf_boolean_t dump_priv;
gf_boolean_t dump_inode;
diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h
index 41197044b66..b0918e43707 100644
--- a/rpc/rpc-lib/src/protocol-common.h
+++ b/rpc/rpc-lib/src/protocol-common.h
@@ -206,6 +206,7 @@ enum gluster_cli_procnum {
GLUSTER_CLI_MOUNT,
GLUSTER_CLI_UMOUNT,
GLUSTER_CLI_HEAL_VOLUME,
+ GLUSTER_CLI_STATEDUMP_VOLUME,
GLUSTER_CLI_MAXVALUE,
};
diff --git a/rpc/xdr/src/cli1-xdr.c b/rpc/xdr/src/cli1-xdr.c
index 7a1c6c91809..8e2adc51c88 100644
--- a/rpc/xdr/src/cli1-xdr.c
+++ b/rpc/xdr/src/cli1-xdr.c
@@ -1099,3 +1099,37 @@ xdr_gf1_cli_heal_vol_rsp (XDR *xdrs, gf1_cli_heal_vol_rsp *objp)
return FALSE;
return TRUE;
}
+
+bool_t
+xdr_gf1_cli_statedump_vol_req (XDR *xdrs, gf1_cli_statedump_vol_req *objp)
+{
+ register int32_t *buf;
+ buf = NULL;
+
+ if (!xdr_string (xdrs, &objp->volname, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->options, ~0))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->option_cnt))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_gf1_cli_statedump_vol_rsp (XDR *xdrs, gf1_cli_statedump_vol_rsp *objp)
+{
+ register int32_t *buf;
+ buf = NULL;
+
+ if (!xdr_int (xdrs, &objp->op_ret))
+ return FALSE;
+ if (!xdr_int (xdrs, &objp->op_errno))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->volname, ~0))
+ return FALSE;
+ if (!xdr_string (xdrs, &objp->op_errstr, ~0))
+ return FALSE;
+ if (!xdr_bytes (xdrs, (char **)&objp->dict.dict_val, (u_int *) &objp->dict.dict_len, ~0))
+ return FALSE;
+ return TRUE;
+}
diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h
index 436bf986d47..56a5f4802ff 100644
--- a/rpc/xdr/src/cli1-xdr.h
+++ b/rpc/xdr/src/cli1-xdr.h
@@ -632,6 +632,25 @@ struct gf1_cli_heal_vol_rsp {
};
typedef struct gf1_cli_heal_vol_rsp gf1_cli_heal_vol_rsp;
+struct gf1_cli_statedump_vol_req {
+ char *volname;
+ char *options;
+ int option_cnt;
+};
+typedef struct gf1_cli_statedump_vol_req gf1_cli_statedump_vol_req;
+
+struct gf1_cli_statedump_vol_rsp {
+ int op_ret;
+ int op_errno;
+ char *volname;
+ char *op_errstr;
+ struct {
+ u_int dict_len;
+ char *dict_val;
+ } dict;
+};
+typedef struct gf1_cli_statedump_vol_rsp gf1_cli_statedump_vol_rsp;
+
/* the xdr functions */
#if defined(__STDC__) || defined(__cplusplus)
@@ -707,6 +726,8 @@ extern bool_t xdr_gf1_cli_umount_req (XDR *, gf1_cli_umount_req*);
extern bool_t xdr_gf1_cli_umount_rsp (XDR *, gf1_cli_umount_rsp*);
extern bool_t xdr_gf1_cli_heal_vol_req (XDR *, gf1_cli_heal_vol_req*);
extern bool_t xdr_gf1_cli_heal_vol_rsp (XDR *, gf1_cli_heal_vol_rsp*);
+extern bool_t xdr_gf1_cli_statedump_vol_req (XDR *, gf1_cli_statedump_vol_req*);
+extern bool_t xdr_gf1_cli_statedump_vol_rsp (XDR *, gf1_cli_statedump_vol_rsp*);
#else /* K&R C */
extern bool_t xdr_gf_cli_defrag_type ();
@@ -781,6 +802,8 @@ extern bool_t xdr_gf1_cli_umount_req ();
extern bool_t xdr_gf1_cli_umount_rsp ();
extern bool_t xdr_gf1_cli_heal_vol_req ();
extern bool_t xdr_gf1_cli_heal_vol_rsp ();
+extern bool_t xdr_gf1_cli_statedump_vol_req ();
+extern bool_t xdr_gf1_cli_statedump_vol_rsp ();
#endif /* K&R C */
diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x
index 9a1f77c0ef7..5ff7aa3e98a 100644
--- a/rpc/xdr/src/cli1-xdr.x
+++ b/rpc/xdr/src/cli1-xdr.x
@@ -466,4 +466,17 @@ struct gf1_cli_heal_vol_rsp {
string volname<>;
string op_errstr<>;
opaque dict<>;
-} ;
+};
+struct gf1_cli_statedump_vol_req {
+ string volname<>;
+ string options<>;
+ int option_cnt;
+};
+
+struct gf1_cli_statedump_vol_rsp {
+ int op_ret;
+ int op_errno;
+ string volname<>;
+ string op_errstr<>;
+ opaque dict<>;
+};
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c
index 808459cfb7c..4e4b73bf493 100644
--- a/xlators/mgmt/glusterd/src/glusterd-handler.c
+++ b/xlators/mgmt/glusterd/src/glusterd-handler.c
@@ -2784,8 +2784,8 @@ rpcsvc_actor_t gd_svc_cli_actors[] = {
[GLUSTER_CLI_STATUS_VOLUME] = {"STATUS_VOLUME", GLUSTER_CLI_STATUS_VOLUME, glusterd_handle_status_volume, NULL, NULL},
[GLUSTER_CLI_MOUNT] = { "MOUNT", GLUSTER_CLI_MOUNT, glusterd_handle_mount, NULL, NULL},
[GLUSTER_CLI_UMOUNT] = { "UMOUNT", GLUSTER_CLI_UMOUNT, glusterd_handle_umount, NULL, NULL},
- [GLUSTER_CLI_HEAL_VOLUME] = { "HEAL_VOLUME", GLUSTER_CLI_HEAL_VOLUME, glusterd_handle_cli_heal_volume, NULL, NULL}
-
+ [GLUSTER_CLI_HEAL_VOLUME] = { "HEAL_VOLUME", GLUSTER_CLI_HEAL_VOLUME, glusterd_handle_cli_heal_volume, NULL, NULL},
+ [GLUSTER_CLI_STATEDUMP_VOLUME] = {"STATEDUMP_VOLUME", GLUSTER_CLI_STATEDUMP_VOLUME, glusterd_handle_cli_statedump_volume, NULL, NULL},
};
struct rpcsvc_program gd_svc_cli_prog = {
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
index 4271fe2460e..bb8cccfbfeb 100644
--- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c
+++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
@@ -1544,6 +1544,7 @@ glusterd_op_build_payload (dict_t **req)
case GD_OP_STATUS_VOLUME:
case GD_OP_REBALANCE:
case GD_OP_HEAL_VOLUME:
+ case GD_OP_STATEDUMP_VOLUME:
{
dict_t *dict = ctx;
dict_copy (dict, req_dict);
@@ -2321,6 +2322,11 @@ glusterd_op_stage_validate (glusterd_op_t op, dict_t *dict, char **op_errstr,
ret = glusterd_op_stage_heal_volume (dict, op_errstr);
break;
+ case GD_OP_STATEDUMP_VOLUME:
+ ret = glusterd_op_stage_statedump_volume (dict,
+ op_errstr);
+ break;
+
default:
gf_log ("", GF_LOG_ERROR, "Unknown op %d",
op);
@@ -2400,21 +2406,25 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr,
ret = glusterd_op_quota (dict, op_errstr);
break;
- case GD_OP_LOG_LEVEL:
- ret = glusterd_op_log_level (dict);
- break;
+ case GD_OP_LOG_LEVEL:
+ ret = glusterd_op_log_level (dict);
+ break;
+
+ case GD_OP_STATUS_VOLUME:
+ ret = glusterd_op_status_volume (dict, op_errstr, rsp_dict);
+ break;
- case GD_OP_STATUS_VOLUME:
- ret = glusterd_op_status_volume (dict, op_errstr, rsp_dict);
- break;
+ case GD_OP_REBALANCE:
+ ret = glusterd_op_rebalance (dict, op_errstr, rsp_dict);
+ break;
- case GD_OP_REBALANCE:
- ret = glusterd_op_rebalance (dict, op_errstr, rsp_dict);
- break;
+ case GD_OP_HEAL_VOLUME:
+ ret = glusterd_op_heal_volume (dict, op_errstr);
+ break;
- case GD_OP_HEAL_VOLUME:
- ret = glusterd_op_heal_volume (dict, op_errstr);
- break;
+ case GD_OP_STATEDUMP_VOLUME:
+ ret = glusterd_op_statedump_volume (dict);
+ break;
default:
gf_log ("", GF_LOG_ERROR, "Unknown op %d",
@@ -3516,6 +3526,7 @@ glusterd_op_free_ctx (glusterd_op_t op, void *ctx)
case GD_OP_STATUS_VOLUME:
case GD_OP_REBALANCE:
case GD_OP_HEAL_VOLUME:
+ case GD_OP_STATEDUMP_VOLUME:
dict_unref (ctx);
break;
case GD_OP_DELETE_VOLUME:
diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
index 4d7e687f2e9..615446a6251 100644
--- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
+++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
@@ -470,6 +470,20 @@ glusterd_op_send_cli_response (glusterd_op_t op, int32_t op_ret,
break;
}
+ case GD_OP_STATEDUMP_VOLUME:
+ {
+ gf1_cli_statedump_vol_rsp rsp = {0,};
+ rsp.op_ret = op_ret;
+ rsp.op_errno = errno;
+ rsp.volname = "";
+ if (op_errstr)
+ rsp.op_errstr = op_errstr;
+ else
+ rsp.op_errstr = "";
+ cli_rsp = &rsp;
+ xdrproc = (xdrproc_t) xdr_gf1_cli_statedump_vol_rsp;
+ break;
+ }
case GD_OP_NONE:
case GD_OP_MAX:
{
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index 3681d4b9565..e27d2209f44 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -4161,3 +4161,112 @@ glusterd_is_volume_replicate (glusterd_volinfo_t *volinfo)
replicates = _gf_true;
return replicates;
}
+
+int
+glusterd_set_dump_options (char *dumpoptions_path, char *options,
+ int option_cnt)
+{
+ int ret = -1;
+ char *dup_options = NULL;
+ char *option = NULL;
+ char *tmpptr = NULL;
+ FILE *fp = NULL;
+
+ if (0 == option_cnt) {
+ ret = 0;
+ goto out;
+ }
+
+ fp = fopen (dumpoptions_path, "w");
+ if (!fp) {
+ ret = -1;
+ goto out;
+ }
+ dup_options = gf_strdup (options);
+ gf_log ("", GF_LOG_INFO, "Recieved following statedump options: %s",
+ dup_options);
+ option = strtok_r (dup_options, " ", &tmpptr);
+ while (option) {
+ fprintf (fp, "%s=yes\n", option);
+ option = strtok_r (NULL, " ", &tmpptr);
+ }
+
+out:
+ if (fp)
+ fclose (fp);
+ return ret;
+}
+
+int
+glusterd_brick_statedump (glusterd_volinfo_t *volinfo,
+ glusterd_brickinfo_t *brickinfo,
+ char *options, int option_cnt)
+{
+ int ret = -1;
+ xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
+ char pidfile_path[PATH_MAX] = {0,};
+ char path[PATH_MAX] = {0,};
+ char dumpoptions_path[PATH_MAX] = {0,};
+ FILE *pidfile = NULL;
+ pid_t pid = -1;
+
+ this = THIS;
+ GF_ASSERT (this);
+ conf = this->private;
+ GF_ASSERT (conf);
+
+ if (uuid_is_null (brickinfo->uuid)) {
+ ret = glusterd_resolve_brick (brickinfo);
+ if (ret) {
+ gf_log ("glusterd", GF_LOG_ERROR,
+ "Cannot resolve brick %s:%s",
+ brickinfo->hostname, brickinfo->path);
+ goto out;
+ }
+ }
+
+ if (uuid_compare (brickinfo->uuid, conf->uuid)) {
+ ret = 0;
+ goto out;
+ }
+
+ GLUSTERD_GET_VOLUME_DIR (path, volinfo, conf);
+ GLUSTERD_GET_BRICK_PIDFILE (pidfile_path, path, brickinfo->hostname,
+ brickinfo->path);
+
+ pidfile = fopen (pidfile_path, "r");
+ if (!pidfile) {
+ gf_log ("", GF_LOG_ERROR, "Unable to open pidfile: %s",
+ pidfile_path);
+ ret = -1;
+ goto out;
+ }
+
+ ret = fscanf (pidfile, "%d", &pid);
+ if (ret <= 0) {
+ gf_log ("", GF_LOG_ERROR, "Unable to get pid of brick process");
+ ret = -1;
+ goto out;
+ }
+
+ snprintf (dumpoptions_path, sizeof (dumpoptions_path),
+ "/tmp/glusterdump.%d.options", pid);
+ glusterd_set_dump_options (dumpoptions_path, options, option_cnt);
+
+
+ gf_log ("", GF_LOG_INFO, "Performing statedump on brick with pid %d",
+ pid);
+
+ kill (pid, SIGUSR1);
+
+ sleep (1);
+ unlink (dumpoptions_path);
+
+ ret = 0;
+out:
+ if (pidfile)
+ fclose (pidfile);
+ return ret;
+}
+
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h
index aca46eae120..3cc137e0579 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.h
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.h
@@ -352,6 +352,11 @@ glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo,
gf_boolean_t
glusterd_is_fuse_available ();
+int
+glusterd_brick_statedump (glusterd_volinfo_t *volinfo,
+ glusterd_brickinfo_t *brickinfo,
+ char *options, int option_cnt);
+
gf_boolean_t
glusterd_is_volume_replicate (glusterd_volinfo_t *volinfo);
gf_boolean_t
diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c
index e1934493a6b..13c1bffa090 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volgen.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c
@@ -193,6 +193,7 @@ static struct volopt_map_entry glusterd_volopt_map[] = {
{VKEY_FEATURES_QUOTA, "features/marker", "quota", "off", NO_DOC, OPT_FLAG_FORCE},
{VKEY_FEATURES_LIMIT_USAGE, "features/quota", "limit-set", NULL, NO_DOC, 0},
{"features.quota-timeout", "features/quota", "timeout", "0", DOC, 0},
+ {"server.statedump-path", "protocol/server", "statedump-path", NULL, NO_DOC, 0},
{NULL, }
};
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
index 816ef9b184e..21e7973863a 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
@@ -447,6 +447,65 @@ out:
return ret;
}
+int
+glusterd_handle_cli_statedump_volume (rpcsvc_request_t *req)
+{
+ int32_t ret = -1;
+ gf1_cli_statedump_vol_req cli_req = {0,};
+ char *dup_volname = NULL;
+ char *dup_options = NULL;
+ dict_t *dict = NULL;
+
+ GF_ASSERT (req);
+
+ ret = -1;
+ if (!xdr_to_generic (req->msg[0], &cli_req,
+ (xdrproc_t)xdr_gf1_cli_statedump_vol_req)) {
+ req->rpc_err = GARBAGE_ARGS;
+ goto out;
+ }
+ gf_log ("glusterd", GF_LOG_INFO, "Recieved statedump request for "
+ "volume %s with options %s", cli_req.volname, cli_req.options);
+ 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;
+
+ dup_options = gf_strdup(cli_req.options);
+ if (!dup_volname)
+ goto out;
+ ret = dict_set_dynstr (dict, "options", dup_options);
+ if (ret)
+ goto out;
+
+ ret = dict_set_int32 (dict, "option_cnt", cli_req.option_cnt);
+ if (ret)
+ goto out;
+
+ ret = glusterd_op_begin (req, GD_OP_STATEDUMP_VOLUME, dict);
+
+ gf_cmd_log ("statedump", "on volume %s %s", cli_req.volname,
+ ((0 == ret) ? "SUCCEEDED" : "FAILED"));
+
+out:
+ if (ret && dict)
+ dict_unref (dict);
+ if (cli_req.volname)
+ free (cli_req.volname);
+ if (cli_req.options)
+ free (cli_req.options);
+ glusterd_friend_sm ();
+ glusterd_op_sm();
+
+ return ret;
+}
/* op-sm */
int
@@ -610,6 +669,37 @@ out:
}
int
+glusterd_op_statedump_volume_args_get (dict_t *dict, char **volname,
+ char **options, int *option_cnt)
+{
+ int ret = -1;
+
+ if (!dict || !volname || !options || !option_cnt)
+ goto out;
+
+ ret = dict_get_str (dict, "volname", volname);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "Unable to get volname");
+ goto out;
+ }
+
+ ret = dict_get_str (dict, "options", options);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "Unable to get options");
+ goto out;
+ }
+
+ ret = dict_get_int32 (dict, "option_cnt", option_cnt);
+ if (ret) {
+ gf_log ("", GF_LOG_ERROR, "Unable to get option count");
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+int
glusterd_op_stage_start_volume (dict_t *dict, char **op_errstr)
{
int ret = 0;
@@ -905,6 +995,46 @@ out:
}
int
+glusterd_op_stage_statedump_volume (dict_t *dict, char **op_errstr)
+{
+ int ret = -1;
+ char *volname = NULL;
+ char *options = NULL;
+ int option_cnt = 0;
+ gf_boolean_t is_running = _gf_false;
+ glusterd_volinfo_t *volinfo = NULL;
+ char msg[2408] = {0,};
+
+ ret = glusterd_op_statedump_volume_args_get (dict, &volname, &options,
+ &option_cnt);
+ if (ret)
+ goto out;
+
+ ret = glusterd_volinfo_find (volname, &volinfo);
+ if (ret) {
+ snprintf (msg, sizeof(msg), "Volume %s does not exist",
+ volname);
+ gf_log ("", GF_LOG_ERROR, "%s", msg);
+ *op_errstr = gf_strdup (msg);
+ goto out;
+ }
+
+ is_running = glusterd_is_volume_started (volinfo);
+ if (!is_running) {
+ snprintf (msg, sizeof(msg), "Volume %s is not in a started"
+ " state", volname);
+ gf_log ("", GF_LOG_ERROR, "%s", msg);
+ *op_errstr = gf_strdup (msg);
+ ret = -1;
+ goto out;
+ }
+
+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;
@@ -1204,3 +1334,34 @@ glusterd_op_heal_volume (dict_t *dict, char **op_errstr)
return ret;
}
+
+int
+glusterd_op_statedump_volume (dict_t *dict)
+{
+ int ret = 0;
+ char *volname = NULL;
+ char *options = NULL;
+ int option_cnt = 0;
+ glusterd_volinfo_t *volinfo = NULL;
+ glusterd_brickinfo_t *brickinfo = NULL;
+
+ ret = glusterd_op_statedump_volume_args_get (dict, &volname, &options,
+ &option_cnt);
+ if (ret)
+ goto out;
+
+ ret = glusterd_volinfo_find (volname, &volinfo);
+ if (ret)
+ goto out;
+ gf_log ("", GF_LOG_DEBUG, "Performing statedump on volume %s", volname);
+ list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
+ ret = glusterd_brick_statedump (volinfo, brickinfo, options,
+ option_cnt);
+ if (ret)
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h
index f5a10189b0e..203f6e975c7 100644
--- a/xlators/mgmt/glusterd/src/glusterd.h
+++ b/xlators/mgmt/glusterd/src/glusterd.h
@@ -80,6 +80,7 @@ typedef enum glusterd_op_ {
GD_OP_STATUS_VOLUME,
GD_OP_REBALANCE,
GD_OP_HEAL_VOLUME,
+ GD_OP_STATEDUMP_VOLUME,
GD_OP_MAX,
} glusterd_op_t;
@@ -541,17 +542,9 @@ 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);
+/* removed other definitions as they have been defined elsewhere in this file*/
+
+int glusterd_handle_cli_statedump_volume (rpcsvc_request_t *req);
int glusterd_handle_defrag_start (glusterd_volinfo_t *volinfo, char *op_errstr,
size_t len, int cmd, defrag_cbk_fn_t cbk);
@@ -590,12 +583,15 @@ int glusterd_op_stage_remove_brick (dict_t *dict, char **op_errstr);
int glusterd_op_stage_rebalance (dict_t *dict, char **op_errstr);
int glusterd_op_rebalance (dict_t *dict, char **op_errstr, dict_t *rsp_dict);
+int glusterd_op_stage_statedump_volume (dict_t *dict, char **op_errstr);
+int glusterd_op_statedump_volume (dict_t *dict);
/* misc */
void glusterd_do_replace_brick (void *data);
int glusterd_op_perform_remove_brick (glusterd_volinfo_t *volinfo, char *brick,
int force, int *need_migrate);
int glusterd_op_stop_volume_args_get (dict_t *dict, char** volname, int *flags);
-
+int glusterd_op_statedump_volume_args_get (dict_t *dict, char **volname,
+ char **options, int *option_cnt);
#endif
diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c
index ec91ba7c21a..3b1f46ad397 100644
--- a/xlators/protocol/server/src/server.c
+++ b/xlators/protocol/server/src/server.c
@@ -508,7 +508,7 @@ reconfigure (xlator_t *this, dict_t *options)
gf_boolean_t trace;
data_t *data;
int ret = 0;
-
+ char *statedump_path = NULL;
conf = this->private;
if (!conf) {
@@ -536,6 +536,27 @@ reconfigure (xlator_t *this, dict_t *options)
" to %d", conf->trace);
}
+
+ /*ret = dict_get_str (options, "statedump-path", &statedump_path);
+ if (!ret) {
+ gf_path_strip_trailing_slashes (statedump_path);
+ if (this->ctx->statedump_path)
+ GF_FREE (this->ctx->statedump_path);
+ this->ctx->statedump_path = gf_strdup (statedump_path);
+ }*/
+ GF_OPTION_RECONF ("statedump-path", statedump_path,
+ options, path, out);
+ if (!statedump_path) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Error while reconfiguring statedump path");
+ ret = -1;
+ goto out;
+ }
+ gf_path_strip_trailing_slashes (statedump_path);
+ if (this->ctx->statedump_path)
+ GF_FREE (this->ctx->statedump_path);
+ this->ctx->statedump_path = gf_strdup (statedump_path);
+
if (!conf->auth_modules)
conf->auth_modules = dict_new ();
@@ -582,7 +603,7 @@ init (xlator_t *this)
int32_t ret = -1;
server_conf_t *conf = NULL;
rpcsvc_listener_t *listener = NULL;
-
+ char *statedump_path = NULL;
GF_VALIDATE_OR_GOTO ("init", this, out);
if (this->children == NULL) {
@@ -614,6 +635,22 @@ init (xlator_t *this)
if (ret)
conf->conf_dir = CONFDIR;
+ /*ret = dict_get_str (this->options, "statedump-path", &statedump_path);
+ if (!ret) {
+ gf_path_strip_trailing_slashes (statedump_path);
+ this->ctx->statedump_path = statedump_path;
+ }*/
+ GF_OPTION_INIT ("statedump-path", statedump_path, path, out);
+ if (statedump_path) {
+ gf_path_strip_trailing_slashes (statedump_path);
+ this->ctx->statedump_path = gf_strdup (statedump_path);
+ } else {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Error setting statedump path");
+ ret = -1;
+ goto out;
+ }
+
/* Authentication modules */
conf->auth_modules = dict_new ();
GF_VALIDATE_OR_GOTO(this->name, conf->auth_modules, out);
@@ -818,5 +855,9 @@ struct volume_options options[] = {
{ .key = {"rpc-auth-allow-insecure"},
.type = GF_OPTION_TYPE_BOOL,
},
+ { .key = {"statedump-path"},
+ .type = GF_OPTION_TYPE_PATH,
+ .default_value = "/tmp"
+ },
{ .key = {NULL} },
};