diff options
Diffstat (limited to 'libglusterfs/src/statedump.c')
| -rw-r--r-- | libglusterfs/src/statedump.c | 211 |
1 files changed, 171 insertions, 40 deletions
diff --git a/libglusterfs/src/statedump.c b/libglusterfs/src/statedump.c index 899d8ef2b..8175faba4 100644 --- a/libglusterfs/src/statedump.c +++ b/libglusterfs/src/statedump.c @@ -53,17 +53,12 @@ gf_proc_dump_unlock (void) pthread_mutex_unlock (&gf_proc_dump_mutex); } - static int -gf_proc_dump_open (char *dump_dir, char *brickname) +gf_proc_dump_open (char *tmpname) { - char path[PATH_MAX] = {0,}; int dump_fd = -1; - 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); + dump_fd = mkstemp (tmpname); if (dump_fd < 0) return -1; @@ -71,7 +66,6 @@ gf_proc_dump_open (char *dump_dir, char *brickname) return 0; } - static void gf_proc_dump_close (void) { @@ -79,6 +73,45 @@ gf_proc_dump_close (void) gf_dump_fd = -1; } +static int +gf_proc_dump_set_path (char *dump_options_file) +{ + int ret = -1; + FILE *fp = NULL; + char buf[256]; + char *key = NULL, *value = NULL; + char *saveptr = NULL; + + fp = fopen (dump_options_file, "r"); + if (!fp) + goto out; + + ret = fscanf (fp, "%s", buf); + + while (ret != EOF) { + key = strtok_r (buf, "=", &saveptr); + if (!key) { + ret = fscanf (fp, "%s", buf); + continue; + } + + value = strtok_r (NULL, "=", &saveptr); + + if (!value) { + ret = fscanf (fp, "%s", buf); + continue; + } + if (!strcmp (key, "path")) { + dump_options.dump_path = gf_strdup (value); + break; + } + } + +out: + if (fp) + fclose (fp); + return ret; +} int gf_proc_dump_add_section (char *key, ...) @@ -381,7 +414,7 @@ gf_proc_dump_xlator_info (xlator_t *top) if (!top) return; - ctx = glusterfs_ctx_get (); + ctx = top->ctx; trav = top; while (trav) { @@ -395,8 +428,6 @@ gf_proc_dump_xlator_info (xlator_t *top) (trav->itable)) { snprintf (itable_key, 1024, "%d.%s.itable", ctx->graph_id, trav->name); - - inode_table_dump (trav->itable, itable_key); } if (!trav->dumpops) { @@ -430,24 +461,20 @@ static void gf_proc_dump_oldgraph_xlator_info (xlator_t *top) { xlator_t *trav = NULL; - glusterfs_ctx_t *ctx = NULL; - char itable_key[1024] = {0,}; if (!top) return; - ctx = glusterfs_ctx_get (); - trav = top; while (trav) { gf_proc_dump_xlator_mem_info_only_in_use (trav); if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode) && (trav->itable)) { - snprintf (itable_key, 1024, "%d.%s.itable", - ctx->graph_id, trav->name); - - inode_table_dump (trav->itable, itable_key); + /*TODO: dump inode table info if necessary by + printing the graph id (taken by glusterfs_cbtx_t) + in the key + */ } if (!trav->dumpops) { @@ -488,6 +515,44 @@ gf_proc_dump_enable_all_options () return 0; } +gf_boolean_t +is_gf_proc_dump_all_disabled () +{ + gf_boolean_t all_disabled = _gf_true; + + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.dump_mem, all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.dump_iobuf, all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.dump_callpool, all_disabled, + out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_priv, + all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_inode, + all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_fd, + all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_inodectx, + all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_fdctx, + all_disabled, out); + GF_CHECK_DUMP_OPTION_ENABLED (dump_options.xl_options.dump_history, + all_disabled, out); + +out: + return all_disabled; +} + +/* These options are dumped by default if glusterdump.options + file exists and it is emtpty +*/ +static int +gf_proc_dump_enable_default_options () +{ + GF_PROC_DUMP_SET_OPTION (dump_options.dump_mem, _gf_true); + GF_PROC_DUMP_SET_OPTION (dump_options.dump_callpool, _gf_true); + + return 0; +} + static int gf_proc_dump_disable_all_options () { @@ -566,28 +631,44 @@ gf_proc_dump_options_init () int ret = -1; FILE *fp = NULL; char buf[256]; - char dumpbuf[GF_DUMP_MAX_BUF_LEN]; char *key = NULL, *value = NULL; char *saveptr = NULL; char dump_option_file[PATH_MAX]; + /* glusterd will create a file glusterdump.<pid>.options and + sets the statedump options for the process and the file is removed + after the statedump is taken. Direct issue of SIGUSR1 does not have + mechanism for considering the statedump options. So to have a way + of configuring the statedump of all the glusterfs processes through + both cli command and SIGUSR1, glusterdump.options file is searched + and the options mentioned in it are given the higher priority. + */ snprintf (dump_option_file, sizeof (dump_option_file), - "/tmp/glusterdump.%d.options", getpid ()); - + DEFAULT_VAR_RUN_DIRECTORY + "/glusterdump.options"); fp = fopen (dump_option_file, "r"); - if (!fp) { - //ENOENT, return success - (void) gf_proc_dump_enable_all_options (); - return 0; + snprintf (dump_option_file, sizeof (dump_option_file), + DEFAULT_VAR_RUN_DIRECTORY + "/glusterdump.%d.options", getpid ()); + + fp = fopen (dump_option_file, "r"); + + if (!fp) { + //ENOENT, return success + (void) gf_proc_dump_enable_all_options (); + return 0; + } } (void) gf_proc_dump_disable_all_options (); + // swallow the errors if setting statedump file path is failed. + ret = gf_proc_dump_set_path (dump_option_file); + ret = fscanf (fp, "%s", buf); while (ret != EOF) { - key = strtok_r (buf, "=", &saveptr); if (!key) { ret = fscanf (fp, "%s", buf); @@ -601,28 +682,33 @@ gf_proc_dump_options_init () continue; } - snprintf (dumpbuf, sizeof (dumpbuf), "[Debug]:key=%s, value=%s\n",key,value); - ret = write (gf_dump_fd, dumpbuf, strlen (dumpbuf)); - gf_proc_dump_parse_set_option (key, value); - } + if (is_gf_proc_dump_all_disabled ()) + (void) gf_proc_dump_enable_default_options (); + + if (fp) + fclose (fp); + return 0; } void -gf_proc_dump_info (int signum) +gf_proc_dump_info (int signum, glusterfs_ctx_t *ctx) { - int i = 0; - int ret = -1; - glusterfs_ctx_t *ctx = NULL; - glusterfs_graph_t *trav = NULL; - char brick_name[PATH_MAX] = {0,}; + int i = 0; + int ret = -1; + glusterfs_graph_t *trav = NULL; + char brick_name[PATH_MAX] = {0,}; + char timestr[256] = {0,}; + char sign_string[512] = {0,}; + char tmp_dump_name[PATH_MAX] = {0,}; + char path[PATH_MAX] = {0,}; + struct timeval tv = {0,}; gf_proc_dump_lock (); - ctx = glusterfs_ctx_get (); if (!ctx) goto out; @@ -631,14 +717,44 @@ gf_proc_dump_info (int signum) } else strncpy (brick_name, "glusterdump", sizeof (brick_name)); - ret = gf_proc_dump_open (ctx->statedump_path, brick_name); + ret = gf_proc_dump_options_init (); if (ret < 0) goto out; - ret = gf_proc_dump_options_init (); + snprintf (path, sizeof (path), "%s/%s.%d.dump.%"PRIu64, + ((dump_options.dump_path != NULL)?dump_options.dump_path: + ((ctx->statedump_path != NULL)?ctx->statedump_path: + DEFAULT_VAR_RUN_DIRECTORY)), brick_name, getpid(), + (uint64_t) time (NULL)); + + snprintf (tmp_dump_name, PATH_MAX, "%s/dumpXXXXXX", + ((dump_options.dump_path != NULL)?dump_options.dump_path: + ((ctx->statedump_path != NULL)?ctx->statedump_path: + DEFAULT_VAR_RUN_DIRECTORY))); + + ret = gf_proc_dump_open (tmp_dump_name); if (ret < 0) goto out; + //continue even though gettimeofday() has failed + ret = gettimeofday (&tv, NULL); + if (0 == ret) { + gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT); + snprintf (timestr + strlen (timestr), + sizeof timestr - strlen (timestr), + ".%"GF_PRI_SUSECONDS, tv.tv_usec); + } + + snprintf (sign_string, sizeof (sign_string), "DUMP-START-TIME: %s\n", + timestr); + + //swallow the errors of write for start and end marker + ret = write (gf_dump_fd, sign_string, strlen (sign_string)); + + memset (sign_string, 0, sizeof (sign_string)); + memset (timestr, 0, sizeof (timestr)); + memset (&tv, 0, sizeof (tv)); + if (GF_PROC_DUMP_IS_OPTION_ENABLED (mem)) { gf_proc_dump_mem_info (); gf_proc_dump_mempool_info (ctx); @@ -670,9 +786,24 @@ gf_proc_dump_info (int signum) i++; } + ret = gettimeofday (&tv, NULL); + if (0 == ret) { + gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT); + snprintf (timestr + strlen (timestr), + sizeof timestr - strlen (timestr), + ".%"GF_PRI_SUSECONDS, tv.tv_usec); + } + + snprintf (sign_string, sizeof (sign_string), "\nDUMP-END-TIME: %s", + timestr); + ret = write (gf_dump_fd, sign_string, strlen (sign_string)); + out: if (gf_dump_fd != -1) gf_proc_dump_close (); + rename (tmp_dump_name, path); + GF_FREE (dump_options.dump_path); + dump_options.dump_path = NULL; gf_proc_dump_unlock (); return; |
