diff options
Diffstat (limited to 'libglusterfs/src/statedump.c')
| -rw-r--r-- | libglusterfs/src/statedump.c | 854 |
1 files changed, 737 insertions, 117 deletions
diff --git a/libglusterfs/src/statedump.c b/libglusterfs/src/statedump.c index 6839c28f6..8175faba4 100644 --- a/libglusterfs/src/statedump.c +++ b/libglusterfs/src/statedump.c @@ -1,118 +1,237 @@ /* - Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.com> + Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com> This file is part of GlusterFS. - GlusterFS is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 3 of the License, - or (at your option) any later version. - - GlusterFS is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - <http://www.gnu.org/licenses/>. + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. */ #include <stdarg.h> -#include <malloc.h> #include "glusterfs.h" #include "logging.h" #include "iobuf.h" #include "statedump.h" #include "stack.h" +#include "common-utils.h" + +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif /* MALLOC_H */ + +/* We don't want gf_log in this function because it may cause + 'deadlock' with statedump. This is because statedump happens + inside a signal handler and cannot afford to block on a lock.*/ +#ifdef gf_log +# undef gf_log +#endif + +#define GF_PROC_DUMP_IS_OPTION_ENABLED(opt) \ + (dump_options.dump_##opt == _gf_true) +#define GF_PROC_DUMP_IS_XL_OPTION_ENABLED(opt) \ + (dump_options.xl_options.dump_##opt == _gf_true) + +extern xlator_t global_xlator; static pthread_mutex_t gf_proc_dump_mutex; static int gf_dump_fd = -1; +gf_dump_options_t dump_options; + -static void +static void gf_proc_dump_lock (void) { - pthread_mutex_lock(&gf_proc_dump_mutex); + pthread_mutex_lock (&gf_proc_dump_mutex); } -static void + +static void gf_proc_dump_unlock (void) { - pthread_mutex_unlock(&gf_proc_dump_mutex); -} + pthread_mutex_unlock (&gf_proc_dump_mutex); +} static int -gf_proc_dump_open (void) +gf_proc_dump_open (char *tmpname) { - char path[256]; int dump_fd = -1; - memset(path, 0, sizeof(path)); - snprintf(path, sizeof(path), "%s.%d",GF_DUMP_LOGFILE_ROOT, getpid()); - - dump_fd = open(path, O_CREAT|O_RDWR|O_TRUNC|O_APPEND, 0600); - if (dump_fd < 0) { - gf_log("", GF_LOG_ERROR, "Unable to open file: %s" - " errno: %d", path, errno); + dump_fd = mkstemp (tmpname); + if (dump_fd < 0) return -1; - } - gf_dump_fd = dump_fd; + gf_dump_fd = dump_fd; return 0; } static void gf_proc_dump_close (void) { - close(gf_dump_fd); + close (gf_dump_fd); gf_dump_fd = -1; } -void -gf_proc_dump_add_section (char *key, ...) +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, ...) +{ + char buf[GF_DUMP_MAX_BUF_LEN]; va_list ap; - int ret; - assert(key); - - memset(buf, 0, sizeof(buf)); - snprintf(buf, GF_DUMP_MAX_BUF_LEN, "\n["); - va_start(ap, key); - vsnprintf(buf + strlen(buf), - GF_DUMP_MAX_BUF_LEN - strlen(buf), key, ap); - va_end(ap); - snprintf(buf + strlen(buf), - GF_DUMP_MAX_BUF_LEN - strlen(buf), "]\n"); - ret = write(gf_dump_fd, buf, strlen(buf)); + GF_ASSERT(key); + + memset (buf, 0, sizeof(buf)); + snprintf (buf, GF_DUMP_MAX_BUF_LEN, "\n["); + va_start (ap, key); + vsnprintf (buf + strlen(buf), + GF_DUMP_MAX_BUF_LEN - strlen (buf), key, ap); + va_end (ap); + snprintf (buf + strlen(buf), + GF_DUMP_MAX_BUF_LEN - strlen (buf), "]\n"); + return write (gf_dump_fd, buf, strlen (buf)); } -void -gf_proc_dump_write (char *key, char *value,...) -{ - - char buf[GF_DUMP_MAX_BUF_LEN]; - int offset = 0; - va_list ap; - int ret; - - offset = strlen(key); - - memset(buf, 0, GF_DUMP_MAX_BUF_LEN); - snprintf(buf, GF_DUMP_MAX_BUF_LEN, "%s",key); - snprintf(buf + offset, GF_DUMP_MAX_BUF_LEN - offset, "="); + +int +gf_proc_dump_write (char *key, char *value,...) +{ + + char buf[GF_DUMP_MAX_BUF_LEN]; + int offset = 0; + va_list ap; + + GF_ASSERT (key); + + offset = strlen (key); + + memset (buf, 0, GF_DUMP_MAX_BUF_LEN); + snprintf (buf, GF_DUMP_MAX_BUF_LEN, "%s", key); + snprintf (buf + offset, GF_DUMP_MAX_BUF_LEN - offset, "="); offset += 1; - va_start(ap, value); - vsnprintf(buf + offset, GF_DUMP_MAX_BUF_LEN - offset, value, ap); - va_end(ap); + va_start (ap, value); + vsnprintf (buf + offset, GF_DUMP_MAX_BUF_LEN - offset, value, ap); + va_end (ap); + + offset = strlen (buf); + snprintf (buf + offset, GF_DUMP_MAX_BUF_LEN - offset, "\n"); + return write (gf_dump_fd, buf, strlen (buf)); +} + +static void +gf_proc_dump_xlator_mem_info (xlator_t *xl) +{ + int i = 0; + struct mem_acct rec = {0,}; + + if (!xl) + return; - offset = strlen(buf); - snprintf(buf + offset, GF_DUMP_MAX_BUF_LEN - offset, "\n"); - ret = write(gf_dump_fd, buf, strlen(buf)); + if (!xl->mem_acct.rec) + return; + + gf_proc_dump_add_section ("%s.%s - Memory usage", xl->type, xl->name); + gf_proc_dump_write ("num_types", "%d", xl->mem_acct.num_types); + + for (i = 0; i < xl->mem_acct.num_types; i++) { + if (!(memcmp (&xl->mem_acct.rec[i], &rec, + sizeof (struct mem_acct)))) + continue; + + gf_proc_dump_add_section ("%s.%s - usage-type %d memusage", + xl->type, xl->name, i); + gf_proc_dump_write ("size", "%u", xl->mem_acct.rec[i].size); + gf_proc_dump_write ("num_allocs", "%u", + xl->mem_acct.rec[i].num_allocs); + gf_proc_dump_write ("max_size", "%u", + xl->mem_acct.rec[i].max_size); + gf_proc_dump_write ("max_num_allocs", "%u", + xl->mem_acct.rec[i].max_num_allocs); + gf_proc_dump_write ("total_allocs", "%u", + xl->mem_acct.rec[i].total_allocs); + } + + return; } +static void +gf_proc_dump_xlator_mem_info_only_in_use (xlator_t *xl) +{ + int i = 0; + + if (!xl) + return; + + if (!xl->mem_acct.rec) + return; + + gf_proc_dump_add_section ("%s.%s - Memory usage", xl->type, xl->name); + gf_proc_dump_write ("num_types", "%d", xl->mem_acct.num_types); + + for (i = 0; i < xl->mem_acct.num_types; i++) { + if (!xl->mem_acct.rec[i].size) + continue; + + gf_proc_dump_add_section ("%s.%s - usage-type %d", xl->type, + xl->name,i); + + gf_proc_dump_write ("size", "%u", + xl->mem_acct.rec[i].size); + gf_proc_dump_write ("max_size", "%u", + xl->mem_acct.rec[i].max_size); + gf_proc_dump_write ("num_allocs", "%u", + xl->mem_acct.rec[i].num_allocs); + gf_proc_dump_write ("max_num_allocs", "%u", + xl->mem_acct.rec[i].max_num_allocs); + gf_proc_dump_write ("total_allocs", "%u", + xl->mem_acct.rec[i].total_allocs); + } + + return; +} + + /* Currently this dumps only mallinfo. More can be built on here */ void @@ -121,93 +240,594 @@ gf_proc_dump_mem_info () #ifdef HAVE_MALLOC_STATS struct mallinfo info; - memset(&info, 0, sizeof(struct mallinfo)); - info = mallinfo(); - - gf_proc_dump_add_section("mallinfo"); - gf_proc_dump_write("mallinfo_arena", "%d", info.arena); - gf_proc_dump_write("mallinfo_ordblks", "%d", info.ordblks); - gf_proc_dump_write("mallinfo_smblks","%d", info.smblks); - gf_proc_dump_write("mallinfo_hblks","%d", info.hblks); - gf_proc_dump_write("mallinfo_hblkhd", "%d", info.hblkhd); - gf_proc_dump_write("mallinfo_usmblks","%d", info.usmblks); - gf_proc_dump_write("mallinfo_fsmblks","%d", info.fsmblks); - gf_proc_dump_write("mallinfo_uordblks","%d", info.uordblks); - gf_proc_dump_write("mallinfo_fordblks", "%d", info.fordblks); - gf_proc_dump_write("mallinfo_keepcost", "%d", info.keepcost); + memset (&info, 0, sizeof (struct mallinfo)); + info = mallinfo (); + + gf_proc_dump_add_section ("mallinfo"); + gf_proc_dump_write ("mallinfo_arena", "%d", info.arena); + gf_proc_dump_write ("mallinfo_ordblks", "%d", info.ordblks); + gf_proc_dump_write ("mallinfo_smblks", "%d", info.smblks); + gf_proc_dump_write ("mallinfo_hblks", "%d", info.hblks); + gf_proc_dump_write ("mallinfo_hblkhd", "%d", info.hblkhd); + gf_proc_dump_write ("mallinfo_usmblks", "%d", info.usmblks); + gf_proc_dump_write ("mallinfo_fsmblks", "%d", info.fsmblks); + gf_proc_dump_write ("mallinfo_uordblks", "%d", info.uordblks); + gf_proc_dump_write ("mallinfo_fordblks", "%d", info.fordblks); + gf_proc_dump_write ("mallinfo_keepcost", "%d", info.keepcost); +#endif + gf_proc_dump_xlator_mem_info(&global_xlator); + +} + +void +gf_proc_dump_mem_info_to_dict (dict_t *dict) +{ + if (!dict) + return; +#ifdef HAVE_MALLOC_STATS + struct mallinfo info; + int ret = -1; + + memset (&info, 0, sizeof(struct mallinfo)); + info = mallinfo (); + + ret = dict_set_int32 (dict, "mallinfo.arena", info.arena); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.ordblks", info.ordblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.smblks", info.smblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.hblks", info.hblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.hblkhd", info.hblkhd); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.usmblks", info.usmblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.fsmblks", info.fsmblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.uordblks", info.uordblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.fordblks", info.fordblks); + if (ret) + return; + + ret = dict_set_int32 (dict, "mallinfo.keepcost", info.keepcost); + if (ret) + return; #endif + return; +} + +void +gf_proc_dump_mempool_info (glusterfs_ctx_t *ctx) +{ + struct mem_pool *pool = NULL; + + gf_proc_dump_add_section ("mempool"); + + list_for_each_entry (pool, &ctx->mempool_list, global_list) { + gf_proc_dump_write ("-----", "-----"); + gf_proc_dump_write ("pool-name", "%s", pool->name); + gf_proc_dump_write ("hot-count", "%d", pool->hot_count); + gf_proc_dump_write ("cold-count", "%d", pool->cold_count); + gf_proc_dump_write ("padded_sizeof", "%lu", + pool->padded_sizeof_type); + gf_proc_dump_write ("alloc-count", "%"PRIu64, pool->alloc_count); + gf_proc_dump_write ("max-alloc", "%d", pool->max_alloc); + + gf_proc_dump_write ("pool-misses", "%"PRIu64, pool->pool_misses); + gf_proc_dump_write ("max-stdalloc", "%d", pool->max_stdalloc); + } +} +void +gf_proc_dump_mempool_info_to_dict (glusterfs_ctx_t *ctx, dict_t *dict) +{ + struct mem_pool *pool = NULL; + char key[GF_DUMP_MAX_BUF_LEN] = {0,}; + int count = 0; + int ret = -1; + + if (!ctx || !dict) + return; + + list_for_each_entry (pool, &ctx->mempool_list, global_list) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.name", count); + ret = dict_set_str (dict, key, pool->name); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.hotcount", count); + ret = dict_set_int32 (dict, key, pool->hot_count); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.coldcount", count); + ret = dict_set_int32 (dict, key, pool->cold_count); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.paddedsizeof", count); + ret = dict_set_uint64 (dict, key, pool->padded_sizeof_type); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.alloccount", count); + ret = dict_set_uint64 (dict, key, pool->alloc_count); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.max_alloc", count); + ret = dict_set_int32 (dict, key, pool->max_alloc); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.max-stdalloc", count); + ret = dict_set_int32 (dict, key, pool->max_stdalloc); + if (ret) + return; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "pool%d.pool-misses", count); + ret = dict_set_uint64 (dict, key, pool->pool_misses); + if (ret) + return; + count++; + } + ret = dict_set_int32 (dict, "mempool-count", count); + + return; } +void gf_proc_dump_latency_info (xlator_t *xl); void -gf_proc_dump_xlator_info (xlator_t *this_xl) +gf_proc_dump_xlator_info (xlator_t *top) +{ + xlator_t *trav = NULL; + glusterfs_ctx_t *ctx = NULL; + char itable_key[1024] = {0,}; + + if (!top) + return; + + ctx = top->ctx; + + trav = top; + while (trav) { + + if (ctx->measure_latency) + gf_proc_dump_latency_info (trav); + + gf_proc_dump_xlator_mem_info(trav); + + if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode) && + (trav->itable)) { + snprintf (itable_key, 1024, "%d.%s.itable", + ctx->graph_id, trav->name); + } + + if (!trav->dumpops) { + trav = trav->next; + continue; + } + + if (trav->dumpops->priv && + GF_PROC_DUMP_IS_XL_OPTION_ENABLED (priv)) + trav->dumpops->priv (trav); + + if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode) && + (trav->dumpops->inode)) + trav->dumpops->inode (trav); + + if (trav->dumpops->fd && + GF_PROC_DUMP_IS_XL_OPTION_ENABLED (fd)) + trav->dumpops->fd (trav); + + if (trav->dumpops->history && + GF_PROC_DUMP_IS_XL_OPTION_ENABLED (history)) + trav->dumpops->history (trav); + + trav = trav->next; + } + + return; +} + +static void +gf_proc_dump_oldgraph_xlator_info (xlator_t *top) { + xlator_t *trav = NULL; - if (!this_xl) + if (!top) return; - while (this_xl) { - if (!this_xl->dumpops) { - this_xl = this_xl->next; + 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)) { + /*TODO: dump inode table info if necessary by + printing the graph id (taken by glusterfs_cbtx_t) + in the key + */ + } + + if (!trav->dumpops) { + trav = trav->next; continue; } - if (this_xl->dumpops->priv) - this_xl->dumpops->priv(this_xl); - if (this_xl->dumpops->inode) - this_xl->dumpops->inode(this_xl); - if (this_xl->dumpops->fd) - this_xl->dumpops->fd(this_xl); - this_xl = this_xl->next; + + if (GF_PROC_DUMP_IS_XL_OPTION_ENABLED (inode) && + (trav->dumpops->inode)) + trav->dumpops->inode (trav); + + if (trav->dumpops->fd && + GF_PROC_DUMP_IS_XL_OPTION_ENABLED (fd)) + trav->dumpops->fd (trav); + + trav = trav->next; } return; } +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); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_history, + _gf_true); + + 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 () +{ + + 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); + GF_PROC_DUMP_SET_OPTION (dump_options.xl_options.dump_history, + _gf_false); + return 0; +} + +static int +gf_proc_dump_parse_set_option (char *key, char *value) +{ + gf_boolean_t *opt_key = NULL; + gf_boolean_t opt_value = _gf_false; + char buf[GF_DUMP_MAX_BUF_LEN]; + int ret = -1; + + if (!strcasecmp (key, "all")) { + (void)gf_proc_dump_enable_all_options (); + return 0; + } else if (!strcasecmp (key, "mem")) { + opt_key = &dump_options.dump_mem; + } else if (!strcasecmp (key, "iobuf")) { + opt_key = &dump_options.dump_iobuf; + } else if (!strcasecmp (key, "callpool")) { + opt_key = &dump_options.dump_callpool; + } else if (!strcasecmp (key, "priv")) { + opt_key = &dump_options.xl_options.dump_priv; + } else if (!strcasecmp (key, "fd")) { + opt_key = &dump_options.xl_options.dump_fd; + } else if (!strcasecmp (key, "inode")) { + opt_key = &dump_options.xl_options.dump_inode; + } else if (!strcasecmp (key, "inodectx")) { + opt_key = &dump_options.xl_options.dump_inodectx; + } else if (!strcasecmp (key, "fdctx")) { + opt_key = &dump_options.xl_options.dump_fdctx; + } else if (!strcasecmp (key, "history")) { + opt_key = &dump_options.xl_options.dump_history; + } + + if (!opt_key) { + //None of dump options match the key, return back + snprintf (buf, sizeof (buf), "[Warning]:None of the options " + "matched key : %s\n", key); + ret = write (gf_dump_fd, buf, strlen (buf)); + + if (ret >= 0) + ret = -1; + goto out; + + } + + opt_value = (strncasecmp (value, "yes", 3) ? + _gf_false: _gf_true); + + GF_PROC_DUMP_SET_OPTION (*opt_key, opt_value); + + ret = 0; +out: + return ret; +} + +static int +gf_proc_dump_options_init () +{ + int ret = -1; + FILE *fp = NULL; + char buf[256]; + 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), + DEFAULT_VAR_RUN_DIRECTORY + "/glusterdump.options"); + fp = fopen (dump_option_file, "r"); + if (!fp) { + 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); + continue; + } + + value = strtok_r (NULL, "=", &saveptr); + + if (!value) { + ret = fscanf (fp, "%s", buf); + continue; + } + + 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) -{ - int ret = -1; - glusterfs_ctx_t *ctx = NULL; - - gf_proc_dump_lock(); - ret = gf_proc_dump_open(); - if (ret < 0) +gf_proc_dump_info (int signum, glusterfs_ctx_t *ctx) +{ + 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 (); + + if (!ctx) + goto out; + + 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 (); + if (ret < 0) goto out; - gf_proc_dump_mem_info(); - ctx = get_global_ctx_ptr(); - if (ctx) { - iobuf_stats_dump(ctx->iobuf_pool); - gf_proc_dump_pending_frames(ctx->pool); - gf_proc_dump_xlator_info(ctx->graph); - } - - gf_proc_dump_close(); + + 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); + } + + if (GF_PROC_DUMP_IS_OPTION_ENABLED (iobuf)) + iobuf_stats_dump (ctx->iobuf_pool); + if (GF_PROC_DUMP_IS_OPTION_ENABLED (callpool)) + gf_proc_dump_pending_frames (ctx->pool); + + if (ctx->master) { + gf_proc_dump_add_section ("fuse"); + gf_proc_dump_xlator_info (ctx->master); + } + + if (ctx->active) { + gf_proc_dump_add_section ("active graph - %d", ctx->graph_id); + gf_proc_dump_xlator_info (ctx->active->top); + } + + i = 0; + list_for_each_entry (trav, &ctx->graphs, list) { + if (trav == ctx->active) + continue; + + gf_proc_dump_add_section ("oldgraph[%d]", i); + + gf_proc_dump_oldgraph_xlator_info (trav->top); + 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: - gf_proc_dump_unlock(); + 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; } -void + +void gf_proc_dump_fini (void) { - pthread_mutex_destroy(&gf_proc_dump_mutex); + pthread_mutex_destroy (&gf_proc_dump_mutex); } void gf_proc_dump_init () { - pthread_mutex_init(&gf_proc_dump_mutex, NULL); + pthread_mutex_init (&gf_proc_dump_mutex, NULL); - return; + return; } + void gf_proc_dump_cleanup (void) { - pthread_mutex_destroy(&gf_proc_dump_mutex); + pthread_mutex_destroy (&gf_proc_dump_mutex); } - |
