diff options
-rw-r--r-- | cli/src/cli-cmd-parser.c | 2 | ||||
-rw-r--r-- | cli/src/cli-cmd-volume.c | 2 | ||||
-rw-r--r-- | libglusterfs/src/Makefile.am | 4 | ||||
-rw-r--r-- | libglusterfs/src/circ-buff.c | 180 | ||||
-rw-r--r-- | libglusterfs/src/circ-buff.h | 72 | ||||
-rw-r--r-- | libglusterfs/src/event-history.c | 90 | ||||
-rw-r--r-- | libglusterfs/src/event-history.h | 52 | ||||
-rw-r--r-- | libglusterfs/src/logging.c | 9 | ||||
-rw-r--r-- | libglusterfs/src/logging.h | 3 | ||||
-rw-r--r-- | libglusterfs/src/mem-types.h | 5 | ||||
-rw-r--r-- | libglusterfs/src/statedump.c | 23 | ||||
-rw-r--r-- | libglusterfs/src/statedump.h | 1 | ||||
-rw-r--r-- | libglusterfs/src/xlator.h | 6 |
13 files changed, 437 insertions, 12 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index e483a1bd4..703a06e84 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -1991,7 +1991,7 @@ gf_boolean_t cli_cmd_validate_dumpoption (const char *arg, char **option) { char *opwords[] = {"all", "nfs", "mem", "iobuf", "callpool", "priv", - "fd", "inode", NULL}; + "fd", "inode", "history", NULL}; char *w = NULL; w = str_getunamb (arg, opwords); diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 6ab1515e3..37b41c81e 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1831,7 +1831,7 @@ struct cli_cmd volume_cmds[] = { "Start healing of volume specified by <VOLNAME>"}, {"volume statedump <VOLNAME> [nfs] [all|mem|iobuf|callpool|priv|fd|" - "inode]...", + "inode|history]...", cli_cmd_volume_statedump_cbk, "perform statedump on bricks"}, diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am index bbe7a2cd7..c7f3d9ba7 100644 --- a/libglusterfs/src/Makefile.am +++ b/libglusterfs/src/Makefile.am @@ -23,7 +23,7 @@ libglusterfs_la_SOURCES = dict.c xlator.c logging.c \ $(CONTRIBDIR)/uuid/parse.c $(CONTRIBDIR)/uuid/unparse.c \ $(CONTRIBDIR)/uuid/uuid_time.c $(CONTRIBDIR)/uuid/compare.c \ $(CONTRIBDIR)/uuid/isnull.c $(CONTRIBDIR)/uuid/unpack.c syncop.c \ - graph-print.c trie.c run.c options.c fd-lk.c + graph-print.c trie.c run.c options.c fd-lk.c circ-buff.c event-history.c nodist_libglusterfs_la_SOURCES = y.tab.c graph.lex.c @@ -37,7 +37,7 @@ noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h \ rbthash.h iatt.h latency.h mem-types.h $(CONTRIBDIR)/uuid/uuidd.h \ $(CONTRIBDIR)/uuid/uuid.h $(CONTRIBDIR)/uuid/uuidP.h \ $(CONTRIB_BUILDDIR)/uuid/uuid_types.h syncop.h graph-utils.h trie.h run.h \ - options.h lkowner.h fd-lk.h + options.h lkowner.h fd-lk.h circ-buff.h event-history.h EXTRA_DIST = graph.l graph.y diff --git a/libglusterfs/src/circ-buff.c b/libglusterfs/src/circ-buff.c new file mode 100644 index 000000000..36f8eeb7b --- /dev/null +++ b/libglusterfs/src/circ-buff.c @@ -0,0 +1,180 @@ +/* + Copyright (c) 2012 Gluster, Inc. <http://www.gluster.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/>. +*/ + +#include "circ-buff.h" + +/* hold lock while calling this function */ +int +__cb_add_entry_buffer (buffer_t *buffer, void *item) +{ + circular_buffer_t *ptr = NULL; + int ret = -1; + //DO we really need the assert here? + GF_ASSERT (buffer->used_len <= buffer->size_buffer); + + if (buffer->use_once == _gf_true && + buffer->used_len == buffer->size_buffer) { + gf_log ("", GF_LOG_WARNING, "buffer %p is use once buffer", + buffer); + return -1; + } else { + if (buffer->used_len == buffer->size_buffer) { + if (buffer->cb[buffer->w_index]) { + ptr = buffer->cb[buffer->w_index]; + if (ptr->data) { + GF_FREE (ptr->data); + ptr->data = NULL; + GF_FREE (ptr); + } + buffer->cb[buffer->w_index] = NULL; + ptr = NULL; + } + } + + buffer->cb[buffer->w_index] = + GF_CALLOC (1, sizeof (circular_buffer_t), + gf_common_mt_circular_buffer_t); + if (!buffer->cb[buffer->w_index]) + return -1; + + buffer->cb[buffer->w_index]->data = item; + ret = gettimeofday (&buffer->cb[buffer->w_index]->tv, NULL); + if (ret == -1) + gf_log_callingfn ("", GF_LOG_WARNING, "getting time of" + "the day failed"); + + buffer->w_index++; + buffer->w_index %= buffer->size_buffer - 1; + //used_buffer size cannot be greater than the total buffer size + + if (buffer->used_len < buffer->size_buffer) + buffer->used_len++; + return buffer->w_index; + } +} + +int +cb_add_entry_buffer (buffer_t *buffer, void *item) +{ + int write_index = -1; + + pthread_mutex_lock (&buffer->lock); + { + write_index = __cb_add_entry_buffer (buffer, item); + } + pthread_mutex_unlock (&buffer->lock); + + return write_index; +} + +void +cb_buffer_show (buffer_t *buffer) +{ + pthread_mutex_lock (&buffer->lock); + { + gf_log ("", GF_LOG_DEBUG, "w_index: %d, size: %"GF_PRI_SIZET + " used_buffer: %d", buffer->w_index, + buffer->size_buffer, + buffer->used_len); + } + pthread_mutex_unlock (&buffer->lock); +} + +void +cb_buffer_dump (buffer_t *buffer, void *data, + int (fn) (circular_buffer_t *buffer, void *data)) +{ + int i = 0; + circular_buffer_t *entry = NULL; + int entries = 0; + + pthread_mutex_lock (&buffer->lock); + { + if (buffer->use_once == _gf_false) { + for (i = (buffer->w_index - 1) ; entries < + buffer->used_len ; entries++) { + entry = buffer->cb[i]; + if (entry) + fn (entry, data); + if (0 == i) + i = buffer->used_len - 1; + else + i = (i - 1) % (buffer->used_len - 1); + } + } else { + for (i = 0; i < buffer->used_len ; i++) { + entry = buffer->cb[i]; + fn (entry, data); + } + } + } + pthread_mutex_unlock (&buffer->lock); +} + +buffer_t * +cb_buffer_new (size_t buffer_size, gf_boolean_t use_once) +{ + buffer_t *buffer = NULL; + + buffer = GF_CALLOC (1, sizeof (*buffer), gf_common_mt_buffer_t); + if (!buffer) { + gf_log ("", GF_LOG_ERROR, "could not allocate the " + "buffer"); + goto out; + } + + buffer->cb = GF_CALLOC (buffer_size, + sizeof (circular_buffer_t *), + gf_common_mt_circular_buffer_t); + if (!buffer->cb) { + gf_log ("", GF_LOG_ERROR, "could not allocate the " + "memory for the circular buffer"); + GF_FREE (buffer); + buffer = NULL; + goto out; + } + + buffer->w_index = 0; + buffer->size_buffer = buffer_size; + buffer->use_once = use_once; + buffer->used_len = 0; + pthread_mutex_init (&buffer->lock, NULL); + +out: + return buffer; +} + +void +cb_buffer_destroy (buffer_t *buffer) +{ + int i = 0; + + if (buffer) { + if (buffer->cb) { + for (i = 0; i < buffer->used_len ; i++) { + if (buffer->cb[i]) + GF_FREE (buffer->cb[i]); + } + GF_FREE (buffer->cb); + } + pthread_mutex_destroy (&buffer->lock); + GF_FREE (buffer); + } +} + diff --git a/libglusterfs/src/circ-buff.h b/libglusterfs/src/circ-buff.h new file mode 100644 index 000000000..d5172500e --- /dev/null +++ b/libglusterfs/src/circ-buff.h @@ -0,0 +1,72 @@ +/* + Copyright (c) 2012 Gluster, Inc. <http://www.gluster.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/>. +*/ + +#ifndef _CB_H +#define _CB_H + +#include "common-utils.h" +#include "logging.h" +#include "mem-types.h" + +#define BUFFER_SIZE 10 +#define TOTAL_SIZE BUFFER_SIZE + 1 + + +struct _circular_buffer { + struct timeval tv; + void *data; +}; + +typedef struct _circular_buffer circular_buffer_t; + +struct _buffer { + unsigned int w_index; + size_t size_buffer; + gf_boolean_t use_once; + /* This variable is assigned the proper value at the time of initing */ + /* the buffer. It indicates, whether the buffer should be used once */ + /* it becomes full. */ + + int used_len; + /* indicates the amount of circular buffer used. */ + + circular_buffer_t **cb; + + pthread_mutex_t lock; +}; + +typedef struct _buffer buffer_t; + +int +cb_add_entry_buffer (buffer_t *buffer, void *item); + +void +cb_buffer_show (buffer_t *buffer); + +buffer_t * +cb_buffer_new (size_t buffer_size,gf_boolean_t use_buffer_once); + +void +cb_buffer_destroy (buffer_t *buffer); + +void +cb_buffer_dump (buffer_t *buffer, void *data, + int (fn) (circular_buffer_t *buffer, void *data)); + +#endif /* _CB_H */ diff --git a/libglusterfs/src/event-history.c b/libglusterfs/src/event-history.c new file mode 100644 index 000000000..812267b7c --- /dev/null +++ b/libglusterfs/src/event-history.c @@ -0,0 +1,90 @@ +/* + Copyright (c) 2012 Gluster, Inc. <http://www.gluster.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/>. +*/ + +#include "event-history.h" + +eh_t * +eh_new (size_t buffer_size, gf_boolean_t use_buffer_once) +{ + eh_t *history = NULL; + buffer_t *buffer = NULL; + + history = GF_CALLOC (1, sizeof (eh_t), gf_common_mt_eh_t); + if (!history) { + gf_log ("", GF_LOG_ERROR, "allocating history failed."); + goto out; + } + + buffer = cb_buffer_new (buffer_size, use_buffer_once); + if (!buffer) { + gf_log ("", GF_LOG_ERROR, "allocating circular buffer failed"); + GF_FREE (history); + history = NULL; + } + + history->buffer = buffer; + + pthread_mutex_init (&history->lock, NULL); +out: + return history; +} + +void +eh_dump (eh_t *history, void *data, + int (dump_fn) (circular_buffer_t *buffer, void *data)) +{ + if (!history) { + gf_log ("", GF_LOG_DEBUG, "history is NULL"); + goto out; + } + + cb_buffer_dump (history->buffer, data, dump_fn); + +out: + return; +} + +int +eh_save_history (eh_t *history, void *data) +{ + int ret = -1; + + ret = cb_add_entry_buffer (history->buffer, data); + + return ret; +} + +int +eh_destroy (eh_t *history) +{ + if (!history) { + gf_log ("", GF_LOG_INFO, "history for the xlator is " + "NULL"); + return -1; + } + + cb_buffer_destroy (history->buffer); + history->buffer = NULL; + + pthread_mutex_destroy (&history->lock); + + GF_FREE (history); + + return 0; +} diff --git a/libglusterfs/src/event-history.h b/libglusterfs/src/event-history.h new file mode 100644 index 000000000..c6e8fb4fa --- /dev/null +++ b/libglusterfs/src/event-history.h @@ -0,0 +1,52 @@ +/* + Copyright (c) 2012 Gluster, Inc. <http://www.gluster.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/>. +*/ + +#ifndef _EH_H +#define _EH_H + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "mem-types.h" +#include "circ-buff.h" + +struct event_hist +{ + buffer_t *buffer; + pthread_mutex_t lock; +}; + +typedef struct event_hist eh_t; + +void +eh_dump (eh_t *event , void *data, + int (fn) (circular_buffer_t *buffer, void *data)); + +eh_t * +eh_new (size_t buffer_size, gf_boolean_t use_buffer_once); + +int +eh_save_history (eh_t *history, void *string); + +int +eh_destroy (eh_t *history); + +#endif /* _EH_H */ diff --git a/libglusterfs/src/logging.c b/libglusterfs/src/logging.c index 55ef087a8..3698b4e73 100644 --- a/libglusterfs/src/logging.c +++ b/libglusterfs/src/logging.c @@ -616,6 +616,15 @@ out: return (0); } +int +gf_log_eh (void *data) +{ + int ret = -1; + + ret = eh_save_history (THIS->history, data); + + return ret; +} int gf_cmd_log_init (const char *filename) diff --git a/libglusterfs/src/logging.h b/libglusterfs/src/logging.h index cb23cb54f..a06a063aa 100644 --- a/libglusterfs/src/logging.h +++ b/libglusterfs/src/logging.h @@ -108,7 +108,8 @@ extern char gf_log_xl_log_set; void gf_log_logrotate (int signum); - +int +gf_log_eh (void *data); void gf_log_globals_init (void); int gf_log_init (const char *filename); void gf_log_cleanup (void); diff --git a/libglusterfs/src/mem-types.h b/libglusterfs/src/mem-types.h index 1ebf4d360..27d472769 100644 --- a/libglusterfs/src/mem-types.h +++ b/libglusterfs/src/mem-types.h @@ -108,6 +108,9 @@ enum gf_common_mem_types_ { gf_common_mt_run_logbuf = 83, gf_common_mt_fd_lk_ctx_t = 84, gf_common_mt_fd_lk_ctx_node_t = 85, - gf_common_mt_end = 86, + gf_common_mt_buffer_t = 86, + gf_common_mt_circular_buffer_t = 87, + gf_common_mt_eh_t = 88, + gf_common_mt_end = 89 }; #endif diff --git a/libglusterfs/src/statedump.c b/libglusterfs/src/statedump.c index 3811ef692..dbbccdb44 100644 --- a/libglusterfs/src/statedump.c +++ b/libglusterfs/src/statedump.c @@ -410,6 +410,10 @@ gf_proc_dump_xlator_info (xlator_t *top) 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; } @@ -472,6 +476,8 @@ gf_proc_dump_enable_all_options () 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; } @@ -490,7 +496,8 @@ gf_proc_dump_disable_all_options () 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; } @@ -521,6 +528,8 @@ gf_proc_dump_parse_set_option (char *key, char *value) opt_key = &dump_options.xl_options.dump_inodectx; } else if (!strncasecmp (key, "fdctx", strlen ("fdctx"))) { opt_key = &dump_options.xl_options.dump_fdctx; + } else if (!strncasecmp (key, "history", strlen ("history"))) { + opt_key = &dump_options.xl_options.dump_history; } if (!opt_key) { @@ -529,8 +538,12 @@ gf_proc_dump_parse_set_option (char *key, char *value) "matched key : %s\n", key); ret = write (gf_dump_fd, buf, strlen (buf)); - ret = -1; - goto out; + /* warning suppression */ + if (ret >= 0) { + ret = -1; + goto out; + } + } opt_value = (strncasecmp (value, "yes", 3) ? @@ -614,11 +627,11 @@ 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 (brick_name); if (ret < 0) goto out; - ret = gf_proc_dump_options_init (brick_name); + ret = gf_proc_dump_open (ctx->statedump_path, brick_name); if (ret < 0) goto out; diff --git a/libglusterfs/src/statedump.h b/libglusterfs/src/statedump.h index cdeb5b7fc..595802117 100644 --- a/libglusterfs/src/statedump.h +++ b/libglusterfs/src/statedump.h @@ -32,6 +32,7 @@ typedef struct gf_dump_xl_options_ { gf_boolean_t dump_fd; gf_boolean_t dump_inodectx; gf_boolean_t dump_fdctx; + gf_boolean_t dump_history; } gf_dump_xl_options_t; typedef struct gf_dump_options_ { diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h index c8eff3353..7604f8c21 100644 --- a/libglusterfs/src/xlator.h +++ b/libglusterfs/src/xlator.h @@ -29,7 +29,7 @@ #include <stdint.h> #include <inttypes.h> - +#include "event-history.h" #include "logging.h" #include "common-utils.h" #include "dict.h" @@ -770,6 +770,8 @@ typedef int32_t (*dumpop_inodectx_to_dict_t) (xlator_t *this, inode_t *ino, typedef int32_t (*dumpop_fdctx_to_dict_t) (xlator_t *this, fd_t *fd, dict_t *dict); +typedef int32_t (*dumpop_eh_t) (xlator_t *this); + struct xlator_dumpops { dumpop_priv_t priv; dumpop_inode_t inode; @@ -781,6 +783,7 @@ struct xlator_dumpops { dumpop_fd_to_dict_t fd_to_dict; dumpop_inodectx_to_dict_t inodectx_to_dict; dumpop_fdctx_to_dict_t fdctx_to_dict; + dumpop_eh_t history; }; typedef struct xlator_list { @@ -818,6 +821,7 @@ struct _xlator { fop_latency_t latencies[GF_FOP_MAXVALUE]; /* Misc */ + eh_t *history; /* event history context */ glusterfs_ctx_t *ctx; glusterfs_graph_t *graph; /* not set for fuse */ inode_table_t *itable; |