diff options
| author | Kaushal M <kaushal@gluster.com> | 2011-09-05 14:33:43 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vijay@gluster.com> | 2011-09-27 06:45:10 -0700 | 
| commit | 45172a5415abc6b2f17eea74d51805ac85cc0072 (patch) | |
| tree | e2576cf6cda22bd0f3109bc358c51fb419f3a390 | |
| parent | 16b7e3bf201686ca03f8c35c20295e05abe52df8 (diff) | |
cli : new volume statedump command
Changes:
        1. Add a new 'volume statedump' command, that performs statedumps of
        all the bricks in the volume and saves them in a specified location.
        2. Add new server option 'server.statedump-path'.
        3. Remove multiple function definitions in glusterd.h
Statedump Information:
The 'volume statedump' command performs statedumps on all the bricks in
a given volume. The syntax of the command is,
        gluster volume statedump <VOLNAME> [type]......
Types include,
        * all
        * mem
        * iobuf
        * callpool
        * priv
        * fd
        * inode
Defaults to 'all' when no type is specified.
The statedump files are created by default in /tmp directory of the
server on which the bricks are present.
This path can be changed by setting the 'server.statedump-path' option.
The statedump files will be named as,
        <brick-name>.<pid of brick process>.dump
Change-Id: I01c0e1a8aad490da818e086d89f292bd2ed06fd4
BUG: 1964
Reviewed-on: http://review.gluster.com/321
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Amar Tumballi <amar@gluster.com>
| -rw-r--r-- | cli/src/cli-cmd-parser.c | 55 | ||||
| -rw-r--r-- | cli/src/cli-cmd-volume.c | 70 | ||||
| -rw-r--r-- | cli/src/cli-rpc-ops.c | 72 | ||||
| -rw-r--r-- | cli/src/cli.h | 4 | ||||
| -rw-r--r-- | libglusterfs/src/common-utils.c | 18 | ||||
| -rw-r--r-- | libglusterfs/src/common-utils.h | 13 | ||||
| -rw-r--r-- | libglusterfs/src/glusterfs.h | 1 | ||||
| -rw-r--r-- | libglusterfs/src/statedump.c | 112 | ||||
| -rw-r--r-- | libglusterfs/src/statedump.h | 5 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/protocol-common.h | 1 | ||||
| -rw-r--r-- | rpc/xdr/src/cli1-xdr.c | 34 | ||||
| -rw-r--r-- | rpc/xdr/src/cli1-xdr.h | 23 | ||||
| -rw-r--r-- | rpc/xdr/src/cli1-xdr.x | 15 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 4 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 35 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-rpc-ops.c | 14 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 109 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 5 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.c | 1 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 161 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 20 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server.c | 45 | 
22 files changed, 732 insertions, 85 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 6d984680e..d3cb1240f 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 000772532..9b85bf819 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 b58e03173..1e77ae0ab 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 4ef1dbe06..0a2fdb54b 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 6ee32cac7..b2e91608b 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 c7d784ca8..82e499b39 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 8247c60fb..57a542bb3 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 cf947996b..525980bfa 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 43330b37c..fb07f5927 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 41197044b..b0918e437 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 7a1c6c918..8e2adc51c 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 436bf986d..56a5f4802 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 9a1f77c0e..5ff7aa3e9 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 808459cfb..4e4b73bf4 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 4271fe246..bb8cccfbf 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 4d7e687f2..615446a62 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 3681d4b95..e27d2209f 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 aca46eae1..3cc137e05 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 e1934493a..13c1bffa0 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 816ef9b18..21e797386 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 f5a10189b..203f6e975 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 ec91ba7c2..3b1f46ad3 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} },  };  | 
