summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli/src/cli-cmd-parser.c2
-rw-r--r--cli/src/cli-cmd-volume.c2
-rw-r--r--libglusterfs/src/Makefile.am4
-rw-r--r--libglusterfs/src/circ-buff.c180
-rw-r--r--libglusterfs/src/circ-buff.h72
-rw-r--r--libglusterfs/src/event-history.c90
-rw-r--r--libglusterfs/src/event-history.h52
-rw-r--r--libglusterfs/src/logging.c9
-rw-r--r--libglusterfs/src/logging.h3
-rw-r--r--libglusterfs/src/mem-types.h5
-rw-r--r--libglusterfs/src/statedump.c23
-rw-r--r--libglusterfs/src/statedump.h1
-rw-r--r--libglusterfs/src/xlator.h6
13 files changed, 437 insertions, 12 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index e483a1bd477..703a06e84a3 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 6ab1515e302..37b41c81e80 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 bbe7a2cd739..c7f3d9ba70b 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 00000000000..36f8eeb7b9a
--- /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 00000000000..d5172500e78
--- /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 00000000000..812267b7c0b
--- /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 00000000000..c6e8fb4fa86
--- /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 55ef087a868..3698b4e7356 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 cb23cb54f06..a06a063aae7 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 1ebf4d36008..27d47276906 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 3811ef69234..dbbccdb44c3 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 cdeb5b7fc0c..595802117d5 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 c8eff335329..7604f8c21e9 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;