diff options
| author | Vijay Bellur <vijay@gluster.com> | 2009-08-15 12:58:08 +0000 | 
|---|---|---|
| committer | Anand V. Avati <avati@dev.gluster.com> | 2009-08-19 17:57:53 -0700 | 
| commit | b4d6c3d1bb461d2c8a396c9ed3881a4da40fc6ab (patch) | |
| tree | 7a5a15665d46a91b9d4d744b0da599c4628d7f6c | |
| parent | a31b0016347b3bc9b341fa0f4541ed137224f593 (diff) | |
TAKE2[PATCH BUG:213 1/1] Support for Process State Dump
Support for process state dump.
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 213 (Support for process state dump)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=213
| -rw-r--r-- | glusterfsd/src/glusterfsd.c | 4 | ||||
| -rw-r--r-- | libglusterfs/src/Makefile.am | 4 | ||||
| -rw-r--r-- | libglusterfs/src/fd.c | 67 | ||||
| -rw-r--r-- | libglusterfs/src/inode.c | 76 | ||||
| -rw-r--r-- | libglusterfs/src/iobuf.c | 104 | ||||
| -rw-r--r-- | libglusterfs/src/iobuf.h | 1 | ||||
| -rw-r--r-- | libglusterfs/src/stack.c | 171 | ||||
| -rw-r--r-- | libglusterfs/src/stack.h | 6 | ||||
| -rw-r--r-- | libglusterfs/src/statedump.c | 213 | ||||
| -rw-r--r-- | libglusterfs/src/statedump.h | 78 | ||||
| -rw-r--r-- | libglusterfs/src/xlator.c | 5 | ||||
| -rw-r--r-- | libglusterfs/src/xlator.h | 22 | ||||
| -rw-r--r-- | xlators/cluster/afr/src/afr.c | 59 | ||||
| -rw-r--r-- | xlators/features/locks/src/posix.c | 55 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-protocol.c | 81 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.c | 45 | 
16 files changed, 983 insertions, 8 deletions
diff --git a/glusterfsd/src/glusterfsd.c b/glusterfsd/src/glusterfsd.c index 3c9e77822d3..7be544957a1 100644 --- a/glusterfsd/src/glusterfsd.c +++ b/glusterfsd/src/glusterfsd.c @@ -62,6 +62,7 @@  #include "common-utils.h"  #include "event.h"  #include "globals.h" +#include "statedump.h"  #include <fnmatch.h> @@ -1157,6 +1158,7 @@ main (int argc, char *argv[])  		return -1;  	}  	gf_log_set_loglevel (cmd_args->log_level); +        gf_proc_dump_init();  	/* setting up environment  */  	lim.rlim_cur = RLIM_INFINITY; @@ -1169,7 +1171,7 @@ main (int argc, char *argv[])  #ifdef DEBUG  	mtrace ();  #endif -	signal (SIGUSR1, (sighandler_t) malloc_stats); +	signal (SIGUSR1, (sighandler_t) gf_proc_dump_info);  #endif  	signal (SIGSEGV, gf_print_trace);  	signal (SIGABRT, gf_print_trace); diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am index 7698661fa42..a3fb923cabc 100644 --- a/libglusterfs/src/Makefile.am +++ b/libglusterfs/src/Makefile.am @@ -6,9 +6,9 @@ libglusterfs_la_LIBADD = @LEXLIB@  lib_LTLIBRARIES = libglusterfs.la -libglusterfs_la_SOURCES = dict.c spec.lex.c y.tab.c xlator.c logging.c  hashfn.c defaults.c scheduler.c common-utils.c transport.c timer.c inode.c call-stub.c compat.c authenticate.c fd.c compat-errno.c event.c mem-pool.c gf-dirent.c syscall.c iobuf.c globals.c +libglusterfs_la_SOURCES = dict.c spec.lex.c y.tab.c xlator.c logging.c  hashfn.c defaults.c scheduler.c common-utils.c transport.c timer.c inode.c call-stub.c compat.c authenticate.c fd.c compat-errno.c event.c mem-pool.c gf-dirent.c syscall.c iobuf.c globals.c statedump.c stack.c -noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h logging.h protocol.h scheduler.h xlator.h transport.h stack.h timer.h list.h inode.h call-stub.h compat.h authenticate.h fd.h revision.h compat-errno.h event.h mem-pool.h byte-order.h gf-dirent.h locking.h syscall.h iobuf.h globals.h +noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h logging.h protocol.h scheduler.h xlator.h transport.h stack.h timer.h list.h inode.h call-stub.h compat.h authenticate.h fd.h revision.h compat-errno.h event.h mem-pool.h byte-order.h gf-dirent.h locking.h syscall.h iobuf.h globals.h statedump.h  EXTRA_DIST = spec.l spec.y diff --git a/libglusterfs/src/fd.c b/libglusterfs/src/fd.c index 8f7616929c2..62536fc5524 100644 --- a/libglusterfs/src/fd.c +++ b/libglusterfs/src/fd.c @@ -21,6 +21,7 @@  #include "glusterfs.h"  #include "inode.h"  #include "dict.h" +#include "statedump.h"  #ifndef _CONFIG_H @@ -685,3 +686,69 @@ fd_ctx_del (fd_t *fd, xlator_t *xlator, uint64_t *value)          return ret;  } + + +void +fd_dump (fd_t *fd, char *prefix) +{ +        char        key[GF_DUMP_MAX_BUF_LEN]; +        inode_t     *inode = NULL; + +        if (!fd) +                return; +     +        memset(key, 0, sizeof(key)); +        gf_proc_dump_build_key(key, prefix, "pid"); +        gf_proc_dump_write(key, "%d", fd->pid); +        gf_proc_dump_build_key(key, prefix, "refcount"); +        gf_proc_dump_write(key, "%d", fd->refcount); +        gf_proc_dump_build_key(key, prefix, "flags"); +        gf_proc_dump_write(key, "%d", fd->flags); +        gf_proc_dump_build_key(key, prefix, "inode"); +        gf_proc_dump_add_section(key); +        inode_dump(inode, key, NULL); +} + + +void +fdentry_dump (fdentry_t *fdentry, char *prefix) +{ +        if (!fdentry) +                return; + +        if (GF_FDENTRY_ALLOCATED != fdentry->next_free) +                return; + +        if (fdentry->fd)  +                fd_dump(fdentry->fd, prefix); +} + +void +fdtable_dump (fdtable_t *fdtable, char *prefix) +{ +        char        key[GF_DUMP_MAX_BUF_LEN]; +        int         i = 0; + +        if (!fdtable) +                return; +     +        memset(key, 0, sizeof(key)); +        gf_proc_dump_build_key(key, prefix, "refcount"); +        gf_proc_dump_write(key, "%d", fdtable->refcount); +        gf_proc_dump_build_key(key, prefix, "maxfds"); +        gf_proc_dump_write(key, "%d", fdtable->max_fds); +        gf_proc_dump_build_key(key, prefix, "first_free"); +        gf_proc_dump_write(key, "%d", fdtable->first_free); +        gf_proc_dump_build_key(key, prefix, "lock"); +        gf_proc_dump_write(key, "%d", fdtable->lock); + +        for ( i = 0 ; i < fdtable->max_fds; i++) { +                if (GF_FDENTRY_ALLOCATED ==  +                                fdtable->fdentries[i].next_free) { +                        gf_proc_dump_build_key(key, prefix, "fdentry[%d]", i); +                        gf_proc_dump_add_section(key); +                        fdentry_dump(&fdtable->fdentries[i], key); +                } +        } +} + diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index 9796071d87e..138e30068d4 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -24,6 +24,7 @@  #include "inode.h"  #include "common-utils.h" +#include "statedump.h"  #include <pthread.h>  #include <sys/types.h>  #include <stdint.h> @@ -35,6 +36,18 @@     move latest accessed dentry to list_head of inode  */ +#define INODE_DUMP_LIST(head, key_buf, key_prefix, list_type, fn) \ +{ \ +        int i = 1;\ +        inode_t *inode = NULL;\ +        list_for_each_entry (inode, head, list) {\ +                gf_proc_dump_build_key(key_buf, key_prefix, "%s.%d",list_type,\ +                                i++);\ +                gf_proc_dump_add_section(key_buf);\ +                inode_dump(inode, key, fn);\ +        }\ +} +  static inode_t *  __inode_unref (inode_t *inode); @@ -1194,3 +1207,66 @@ unlock:  	return ret;  } + +void +inode_dump (inode_t *inode, char *prefix, inode_priv_dump_fn fn) +{ +        char key[GF_DUMP_MAX_BUF_LEN]; +        int  ret; + +        if (!inode)  +                return; + +	ret = TRY_LOCK(&inode->lock); + +        if (ret != 0) { +                gf_log("", GF_LOG_WARNING, "Unable to dump inode" +                " errno: %d", errno); +                return; +        } + +        gf_proc_dump_build_key(key, prefix, "nlookup"); +        gf_proc_dump_write(key, "%ld", inode->nlookup); +        gf_proc_dump_build_key(key, prefix, "generation"); +        gf_proc_dump_write(key, "%ld", inode->generation); +        gf_proc_dump_build_key(key, prefix, "ref"); +        gf_proc_dump_write(key, "%u", inode->ref); +        gf_proc_dump_build_key(key, prefix, "ino"); +        gf_proc_dump_write(key, "%ld", inode->ino); +        gf_proc_dump_build_key(key, prefix, "st_mode"); +        gf_proc_dump_write(key, "%d", inode->st_mode); +	UNLOCK(&inode->lock); +        if (fn) +                fn (inode); +} + +void +inode_table_dump (inode_table_t *itable, char *prefix, inode_priv_dump_fn fn) +{ +     +        char key[GF_DUMP_MAX_BUF_LEN]; + +        if (!itable) +                return; +     +        memset(key, 0, sizeof(key)); +        gf_proc_dump_build_key(key, prefix, "hashsize"); +        gf_proc_dump_write(key, "%d", itable->hashsize); +        gf_proc_dump_build_key(key, prefix, "name"); +        gf_proc_dump_write(key, "%s", itable->name); +     +        gf_proc_dump_build_key(key, prefix, "lru_limit"); +        gf_proc_dump_write(key, "%d", itable->lru_limit); +        gf_proc_dump_build_key(key, prefix, "active_size"); +        gf_proc_dump_write(key, "%d", itable->active_size); +        gf_proc_dump_build_key(key, prefix, "lru_size"); +        gf_proc_dump_write(key, "%d", itable->lru_size); +        gf_proc_dump_build_key(key, prefix, "purge_size"); +        gf_proc_dump_write(key, "%d", itable->purge_size); + +	pthread_mutex_lock(&itable->lock); +        INODE_DUMP_LIST(&itable->active, key, prefix, "active", fn); +        INODE_DUMP_LIST(&itable->lru, key, prefix, "lru", fn); +        INODE_DUMP_LIST(&itable->purge, key, prefix, "purge", fn); +} + diff --git a/libglusterfs/src/iobuf.c b/libglusterfs/src/iobuf.c index 6d6fca13388..e9408f86bac 100644 --- a/libglusterfs/src/iobuf.c +++ b/libglusterfs/src/iobuf.c @@ -19,6 +19,7 @@  #include "iobuf.h" +#include "statedump.h"  #include <stdio.h> @@ -636,3 +637,106 @@ iobref_size (struct iobref *iobref)  out:          return size;  } + +void  +iobuf_info_dump (struct iobuf *iobuf, const char *key_prefix) +{ +        char   key[GF_DUMP_MAX_BUF_LEN]; +        struct iobuf my_iobuf; +        int    ret = 0; + +        if (!iobuf)  +                return; + +        memset(&my_iobuf, 0, sizeof(my_iobuf)); +         +        ret = TRY_LOCK(&iobuf->lock); +        if (ret) { +                gf_log("", GF_LOG_WARNING, "Unable to dump iobuf" +                " errno: %d", errno); +                return; +        } +        memcpy(&my_iobuf, iobuf, sizeof(my_iobuf)); +        UNLOCK(&iobuf->lock); + +	gf_proc_dump_build_key(key, key_prefix,"ref"); +        gf_proc_dump_write(key, "%d", my_iobuf.ref); +	gf_proc_dump_build_key(key, key_prefix,"ptr"); +        gf_proc_dump_write(key, "%p", my_iobuf.ptr); + +} + +void  +iobuf_arena_info_dump (struct iobuf_arena *iobuf_arena, const char *key_prefix) +{ +	char key[GF_DUMP_MAX_BUF_LEN]; +	int  i = 1; +        struct iobuf *trav; + +	if (!iobuf_arena) +                return; + +        gf_proc_dump_build_key(key, key_prefix,"mem_base"); +        gf_proc_dump_write(key, "%p", iobuf_arena->mem_base); +	gf_proc_dump_build_key(key, key_prefix, "active_cnt"); +        gf_proc_dump_write(key, "%d", iobuf_arena->active_cnt); +	gf_proc_dump_build_key(key, key_prefix, "passive_cnt"); +        gf_proc_dump_write(key, "%d", iobuf_arena->passive_cnt); +	list_for_each_entry (trav, &iobuf_arena->active.list, list) { +                gf_proc_dump_build_key(key, key_prefix,"active_iobuf.%d", i++); +                gf_proc_dump_add_section(key); +                iobuf_info_dump(trav, key); +        } + +        i = 1; +        list_for_each_entry (trav, &iobuf_arena->passive.list, list) { +                gf_proc_dump_build_key(key, key_prefix, +                                        "passive_iobuf.%d",i++); +                gf_proc_dump_add_section(key); +                iobuf_info_dump(trav, key); +        } + +} + +void +iobuf_stats_dump (struct iobuf_pool *iobuf_pool) +{ +     +        char               msg[1024]; +        struct iobuf_arena *trav; +        int                i = 1; +        int                ret = -1; + +        if (!iobuf_pool) +                return; + +        memset(msg, 0, sizeof(msg)); + +        ret = pthread_mutex_trylock(&iobuf_pool->mutex); + +        if (ret) { +                gf_log("", GF_LOG_WARNING, "Unable to dump iobuf pool" +                " errno: %d", errno); +                return; +        } +        gf_proc_dump_add_section("iobuf.global"); +        gf_proc_dump_write("iobuf.global.iobuf_pool","%p", iobuf_pool); +        gf_proc_dump_write("iobuf.global.iobuf_pool.page_size", "%d", +						 iobuf_pool->page_size); +        gf_proc_dump_write("iobuf.global.iobuf_pool.arena_size", "%d", +						 iobuf_pool->arena_size); +        gf_proc_dump_write("iobuf.global.iobuf_pool.arena_cnt", "%d", +						 iobuf_pool->arena_cnt); + +        list_for_each_entry (trav, &iobuf_pool->arenas.list, list) { +                snprintf(msg, sizeof(msg), "iobuf.global.iobuf_pool.arena.%d", +                                                                            i); +		gf_proc_dump_add_section(msg); +                iobuf_arena_info_dump(trav,msg); +                i++; +        } +         +        pthread_mutex_unlock(&iobuf_pool->mutex); + +        return; +} diff --git a/libglusterfs/src/iobuf.h b/libglusterfs/src/iobuf.h index d17c1db486d..de95da324a6 100644 --- a/libglusterfs/src/iobuf.h +++ b/libglusterfs/src/iobuf.h @@ -123,5 +123,6 @@ int iobref_merge (struct iobref *to, struct iobref *from);  size_t iobuf_size (struct iobuf *iobuf);  size_t iobref_size (struct iobref *iobref); +void   iobuf_stats_dump (struct iobuf_pool *iobuf_pool);  #endif /* !_IOBUF_H_ */ diff --git a/libglusterfs/src/stack.c b/libglusterfs/src/stack.c new file mode 100644 index 00000000000..453248479b3 --- /dev/null +++ b/libglusterfs/src/stack.c @@ -0,0 +1,171 @@ +/* +  Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.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 "statedump.h" +#include "stack.h" + +static inline +int call_frames_count (call_frame_t *call_frame)  +{ +        call_frame_t *pos; +        int32_t count = 0; + +        if (!call_frame) +                return count; + +        for (pos = call_frame; pos != NULL; pos = pos->next) +                count++; + +        return count; +} + +void +gf_proc_dump_call_frame (call_frame_t *call_frame, const char *key_buf,...) +{ +     +        char prefix[GF_DUMP_MAX_BUF_LEN]; +        va_list ap; +        char key[GF_DUMP_MAX_BUF_LEN]; +        call_frame_t my_frame; +        int  ret = -1; + +        if (!call_frame) +                return; + +        assert(key_buf); + +        memset(prefix, 0, sizeof(prefix)); +        memset(&my_frame, 0, sizeof(my_frame)); +        va_start(ap, key_buf); +        vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap);  +        va_end(ap); + +        ret = TRY_LOCK(&call_frame->lock); +        if (ret) { +                gf_log("", GF_LOG_WARNING, "Unable to dump call frame" +                " errno: %d", errno); +                return; +        } + +        memcpy(&my_frame, call_frame, sizeof(my_frame)); +        UNLOCK(&call_frame->lock); + +	gf_proc_dump_build_key(key, prefix,"ref_count"); +        gf_proc_dump_write(key, "%d", my_frame.ref_count); +	gf_proc_dump_build_key(key, prefix,"translator"); +        gf_proc_dump_write(key, "%s", my_frame.this->name); +	gf_proc_dump_build_key(key, prefix,"complete"); +        gf_proc_dump_write(key, "%d", my_frame.complete); +        if (my_frame.parent) { +                gf_proc_dump_build_key(key, prefix,"parent"); +                gf_proc_dump_write(key, "%s", my_frame.parent->this->name); +        } +} + + +void +gf_proc_dump_call_stack (call_stack_t *call_stack, const char *key_buf,...) +{ +        char prefix[GF_DUMP_MAX_BUF_LEN]; +        va_list ap; +        call_frame_t *trav; +        int32_t cnt, i; +        char key[GF_DUMP_MAX_BUF_LEN]; + +        if (!call_stack) +                return; + +        assert(key_buf); + +        cnt = call_frames_count(&call_stack->frames); + +        memset(prefix, 0, sizeof(prefix)); +        va_start(ap, key_buf); +        vsnprintf(prefix, GF_DUMP_MAX_BUF_LEN, key_buf, ap);  +        va_end(ap); + +	gf_proc_dump_build_key(key, prefix,"uid"); +        gf_proc_dump_write(key, "%d", call_stack->uid); +	gf_proc_dump_build_key(key, prefix,"gid"); +        gf_proc_dump_write(key, "%d", call_stack->gid); +	gf_proc_dump_build_key(key, prefix,"pid"); +        gf_proc_dump_write(key, "%d", call_stack->pid); +	gf_proc_dump_build_key(key, prefix,"unique"); +        gf_proc_dump_write(key, "%Ld", call_stack->unique); + +	gf_proc_dump_build_key(key, prefix,"op"); +        if ((call_stack->type == GF_OP_TYPE_FOP_REQUEST) || +                (call_stack->type == GF_OP_TYPE_FOP_REPLY)) { +                gf_proc_dump_write(key, "%s", gf_fop_list[call_stack->op]); +        } else if ((call_stack->type == GF_OP_TYPE_MOP_REQUEST) || +                (call_stack->type == GF_OP_TYPE_MOP_REPLY)) { +                gf_proc_dump_write(key, "%s", gf_mop_list[call_stack->op]); +        } else if ((call_stack->type == GF_OP_TYPE_CBK_REQUEST) || +                (call_stack->type == GF_OP_TYPE_CBK_REPLY)) { +                gf_proc_dump_write(key, "%s", gf_cbk_list[call_stack->op]); +        } +     +	gf_proc_dump_build_key(key, prefix,"type"); +        gf_proc_dump_write(key, "%d", call_stack->type); +	gf_proc_dump_build_key(key, prefix,"cnt"); +        gf_proc_dump_write(key, "%d", cnt); + +        trav = &call_stack->frames; + +        for (i = 1; i <= cnt; i++) { +                if (trav) { +                        gf_proc_dump_add_section("%s.frame.%d", prefix, i); +                        gf_proc_dump_call_frame(trav, "%s.frame.%d", prefix, i); +                        trav = trav->next;  +                } +        } +} + +void +gf_proc_dump_pending_frames (call_pool_t *call_pool) +{ +		 +        call_stack_t     *trav = NULL; +        int              i = 1; +        int              ret = -1; + +        if (!call_pool) +                return; + +        ret = TRY_LOCK (&(call_pool->lock)); +        if (ret) { +                gf_log("", GF_LOG_WARNING, "Unable to dump call pool" +                " errno: %d", errno); +                return; +        } + +         +        gf_proc_dump_add_section("global.callpool"); +        gf_proc_dump_write("global.callpool","%p", call_pool); +        gf_proc_dump_write("global.callpool.cnt","%d", call_pool->cnt); + + +        list_for_each_entry (trav, &call_pool->all_frames, all_frames) { +                gf_proc_dump_add_section("global.callpool.stack.%d",i); +                gf_proc_dump_call_stack(trav, "global.callpool.stack.%d", i); +                i++; +        } +	UNLOCK (&(call_pool->lock)); +} + diff --git a/libglusterfs/src/stack.h b/libglusterfs/src/stack.h index e7c1cbd152d..94297255607 100644 --- a/libglusterfs/src/stack.h +++ b/libglusterfs/src/stack.h @@ -1,4 +1,4 @@ -/* +/*     Copyright (c) 2006-2009 Z RESEARCH, Inc. <http://www.zresearch.com>    This file is part of GlusterFS. @@ -74,6 +74,7 @@ struct _call_frame_t {  	int32_t       ref_count;  	gf_lock_t     lock;  	void         *cookie;      /* unique cookie */ +	gf_boolean_t  complete;  };  struct _call_stack_t { @@ -208,6 +209,7 @@ STACK_DESTROY (call_stack_t *stack)  		_parent->ref_count--;					\                  old_THIS = THIS;                                        \                  THIS = _parent->this;                                   \ +                frame->complete = _gf_true;                             \  		fn (_parent, frame->cookie, _parent->this, params);	\                  THIS = old_THIS;                                        \  	} while (0) @@ -281,5 +283,7 @@ create_frame (xlator_t *xl, call_pool_t *pool)  	return &stack->frames;  } +void +gf_proc_dump_pending_frames(call_pool_t *call_pool);  #endif /* _STACK_H */ diff --git a/libglusterfs/src/statedump.c b/libglusterfs/src/statedump.c new file mode 100644 index 00000000000..6839c28f6e9 --- /dev/null +++ b/libglusterfs/src/statedump.c @@ -0,0 +1,213 @@ +/* +  Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.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 <stdarg.h> +#include <malloc.h> +#include "glusterfs.h" +#include "logging.h" +#include "iobuf.h" +#include "statedump.h" +#include "stack.h" + + +static pthread_mutex_t  gf_proc_dump_mutex; +static int gf_dump_fd = -1; + +static void  +gf_proc_dump_lock (void) +{ +	pthread_mutex_lock(&gf_proc_dump_mutex); +} + +static void  +gf_proc_dump_unlock (void) +{ +	pthread_mutex_unlock(&gf_proc_dump_mutex); +}  + +static int +gf_proc_dump_open (void) +{ +        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); +                return -1; +        } + +	gf_dump_fd = dump_fd; +        return 0; +} + +static void +gf_proc_dump_close (void) +{ +        close(gf_dump_fd); +        gf_dump_fd = -1; +} + +void +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)); +} + +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, "="); +        offset += 1; +        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"); +        ret = write(gf_dump_fd, buf, strlen(buf)); +} + + +/* Currently this dumps only mallinfo. More can be built on here */ +void +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); +#endif + +} + + +void +gf_proc_dump_xlator_info (xlator_t *this_xl) +{ + +        if (!this_xl) +                return; + +        while (this_xl) { +                if (!this_xl->dumpops) { +                        this_xl = this_xl->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; +        } + +        return; +} + + +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)  +                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(); +out: +        gf_proc_dump_unlock(); + +        return; +} + +void  +gf_proc_dump_fini (void) +{ +	pthread_mutex_destroy(&gf_proc_dump_mutex); +} + + +void +gf_proc_dump_init () +{ +	pthread_mutex_init(&gf_proc_dump_mutex, NULL); + +	return; +} + +void +gf_proc_dump_cleanup (void) +{ +	pthread_mutex_destroy(&gf_proc_dump_mutex); +} + diff --git a/libglusterfs/src/statedump.h b/libglusterfs/src/statedump.h new file mode 100644 index 00000000000..9ac50ec0c0a --- /dev/null +++ b/libglusterfs/src/statedump.h @@ -0,0 +1,78 @@ +/* +  Copyright (c) 2009 Z RESEARCH, Inc. <http://www.zresearch.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 STATEDUMP_H +#define STATEDUMP_H    + +#include <stdarg.h> +#include "inode.h" + +#define GF_DUMP_MAX_BUF_LEN 4096 + +#define GF_DUMP_LOGFILE_ROOT "/tmp/glusterdump" +#define GF_DUMP_LOGFILE_ROOT_LEN 256 + +static inline +void _gf_proc_dump_build_key (char *key, const char *prefix, char *fmt,...) +{ +        char buf[GF_DUMP_MAX_BUF_LEN]; +        va_list ap; + +        memset(buf, 0, sizeof(buf)); +        va_start(ap, fmt); +        vsnprintf(buf, GF_DUMP_MAX_BUF_LEN, fmt, ap); +        va_end(ap); +        snprintf(key, GF_DUMP_MAX_BUF_LEN, "%s.%s", prefix, buf);   +} + +#define gf_proc_dump_build_key(key, key_prefix, fmt...) \ +{\ +        _gf_proc_dump_build_key(key, key_prefix, ##fmt);\ +} + +typedef void (*inode_priv_dump_fn) (inode_t *); + +void +gf_proc_dump_init(); + +void  +gf_proc_dump_fini(void); + +void +gf_proc_dump_cleanup(void); + +void +gf_proc_dump_info(int signum); + +void +gf_proc_dump_add_section(char *key,...); + +void +gf_proc_dump_write(char *key, char *value,...); + +void +inode_table_dump(inode_table_t *itable, char *prefix, inode_priv_dump_fn fn); + +void +fdtable_dump(fdtable_t *fdtable, char *prefix); + +void +inode_dump(inode_t *inode, char *prefix, inode_priv_dump_fn fn); +#endif /* STATEDUMP_H */ diff --git a/libglusterfs/src/xlator.c b/libglusterfs/src/xlator.c index a3f8ea8fc2e..def1ad1df45 100644 --- a/libglusterfs/src/xlator.c +++ b/libglusterfs/src/xlator.c @@ -740,6 +740,11 @@ xlator_set_type (xlator_t *xl,  			"dlsym(notify) on %s -- neglecting", dlerror ());  	} +	if (!(xl->dumpops = dlsym (handle, "dumpops"))) { +		gf_log ("xlator", GF_LOG_DEBUG, +			"dlsym(dumpops) on %s -- neglecting", dlerror ()); +	} +  	INIT_LIST_HEAD (&xl->volume_options);  	vol_opt = CALLOC (1, sizeof (volume_opt_list_t)); diff --git a/libglusterfs/src/xlator.h b/libglusterfs/src/xlator.h index e8fc9d2503b..2e815af911a 100644 --- a/libglusterfs/src/xlator.h +++ b/libglusterfs/src/xlator.h @@ -806,6 +806,19 @@ struct xlator_cbks {  	cbk_release_t   releasedir;  }; +typedef int32_t (*dumpop_priv_t) (xlator_t *this); + +typedef int32_t (*dumpop_inode_t) (xlator_t *this); + +typedef int32_t (*dumpop_fd_t)  (xlator_t   *this); + +                               +struct xlator_dumpops { +	dumpop_priv_t            priv; +	dumpop_inode_t           inode; +        dumpop_fd_t              fd; +}; +  typedef struct xlator_list {  	xlator_t           *xlator;  	struct xlator_list *next; @@ -859,10 +872,11 @@ struct _xlator {  	dict_t        *options;  	/* Set after doing dlopen() */ -	struct xlator_fops *fops; -	struct xlator_mops *mops; -	struct xlator_cbks *cbks; -	struct list_head   volume_options;  /* list of volume_option_t */ +	struct xlator_fops    *fops; +	struct xlator_mops    *mops; +	struct xlator_cbks    *cbks; +	struct xlator_dumpops *dumpops; +	struct list_head      volume_options;  /* list of volume_option_t */  	void              (*fini) (xlator_t *this);  	int32_t           (*init) (xlator_t *this); diff --git a/xlators/cluster/afr/src/afr.c b/xlators/cluster/afr/src/afr.c index 6b3b05c6b3c..6b7b007aeb8 100644 --- a/xlators/cluster/afr/src/afr.c +++ b/xlators/cluster/afr/src/afr.c @@ -43,6 +43,7 @@  #include "compat-errno.h"  #include "compat.h"  #include "byte-order.h" +#include "statedump.h"  #include "fd.h" @@ -2158,6 +2159,60 @@ out:  	return 0;  } +int +afr_priv_dump (xlator_t *this) +{ +	afr_private_t *priv = NULL; +        char  key_prefix[GF_DUMP_MAX_BUF_LEN]; +        char  key[GF_DUMP_MAX_BUF_LEN]; +        int   i = 0; + + +        assert(this); +	priv = this->private; + +        assert(priv); +        snprintf(key_prefix, GF_DUMP_MAX_BUF_LEN, "%s.%s", this->type, this->name); +        gf_proc_dump_add_section(key_prefix); +        gf_proc_dump_build_key(key, key_prefix, "child_count"); +        gf_proc_dump_write(key, "%u", priv->child_count); +        gf_proc_dump_build_key(key, key_prefix, "read_child_rr"); +        gf_proc_dump_write(key, "%u", priv->read_child_rr); +	for (i = 0; i < priv->child_count; i++) { +                gf_proc_dump_build_key(key, key_prefix, "child_up[%d]", i); +                gf_proc_dump_write(key, "%d", priv->child_up[i]); +                gf_proc_dump_build_key(key, key_prefix,  +                                        "pending_key[%d]", i); +                gf_proc_dump_write(key, "%s", priv->pending_key[i]); +        } +        gf_proc_dump_build_key(key, key_prefix, "data_self_heal"); +        gf_proc_dump_write(key, "%d", priv->data_self_heal); +        gf_proc_dump_build_key(key, key_prefix, "metadata_self_heal"); +        gf_proc_dump_write(key, "%d", priv->metadata_self_heal); +        gf_proc_dump_build_key(key, key_prefix, "entry_self_heal"); +        gf_proc_dump_write(key, "%d", priv->entry_self_heal); +        gf_proc_dump_build_key(key, key_prefix, "data_change_log"); +        gf_proc_dump_write(key, "%d", priv->data_change_log); +        gf_proc_dump_build_key(key, key_prefix, "metadata_change_log"); +        gf_proc_dump_write(key, "%d", priv->metadata_change_log); +        gf_proc_dump_build_key(key, key_prefix, "entry_change_log"); +        gf_proc_dump_write(key, "%d", priv->entry_change_log); +        gf_proc_dump_build_key(key, key_prefix, "read_child"); +        gf_proc_dump_write(key, "%d", priv->read_child); +        gf_proc_dump_build_key(key, key_prefix, "favorite_child"); +        gf_proc_dump_write(key, "%u", priv->favorite_child); +        gf_proc_dump_build_key(key, key_prefix, "data_lock_server_count"); +        gf_proc_dump_write(key, "%u", priv->data_lock_server_count); +        gf_proc_dump_build_key(key, key_prefix, "metadata_lock_server_count"); +        gf_proc_dump_write(key, "%u", priv->metadata_lock_server_count); +        gf_proc_dump_build_key(key, key_prefix, "entry_lock_server_count"); +        gf_proc_dump_write(key, "%u", priv->entry_lock_server_count); +        gf_proc_dump_build_key(key, key_prefix, "wait_count"); +        gf_proc_dump_write(key, "%u", priv->wait_count); + +        return 0; +} +  /**   * find_child_index - find the child's index in the array of subvolumes @@ -2587,6 +2642,10 @@ struct xlator_fops fops = {  struct xlator_mops mops = {  }; +struct xlator_dumpops dumpops = { +        .priv       = afr_priv_dump, +}; +  struct xlator_cbks cbks = {          .release     = afr_release, diff --git a/xlators/features/locks/src/posix.c b/xlators/features/locks/src/posix.c index d672beaebc3..7389e1e6afd 100644 --- a/xlators/features/locks/src/posix.c +++ b/xlators/features/locks/src/posix.c @@ -36,6 +36,7 @@  #include "locks.h"  #include "common.h" +#include "statedump.h"  #ifndef LLONG_MAX  #define LLONG_MAX LONG_LONG_MAX /* compat with old gcc */ @@ -768,6 +769,57 @@ pl_forget (xlator_t *this,  } +void +pl_dump_inode_priv (inode_t *inode) +{ + +        int ret = -1; +        uint64_t   tmp_pl_inode = 0; +        pl_inode_t *pl_inode = NULL; +        char key[GF_DUMP_MAX_BUF_LEN]; + +        if (!inode) +                return; + +	ret = inode_ctx_get (inode, inode->table->xl, &tmp_pl_inode); + +	if (ret != 0)  +                return; +                 +        pl_inode = (pl_inode_t *)(long)tmp_pl_inode; + +        if (!pl_inode)  +                return; + +        gf_proc_dump_build_key(key,  +                               "xlator.feature.locks.inode", +                               "%ld.%s",inode->ino, "mandatory"); +        gf_proc_dump_write(key, "%d", pl_inode->mandatory); +} + + + +/* + * pl_dump_inode - inode dump function for posix locks + * + */ +int +pl_dump_inode (xlator_t *this) +{ + +        assert(this); +         +        if (this->itable) { +                inode_table_dump(this->itable, +                                 "xlator.features.locks.inode_table", +                                  pl_dump_inode_priv); +        } + +	return 0; +} + + +  int  init (xlator_t *this)  { @@ -864,6 +916,9 @@ struct xlator_fops fops = {  struct xlator_mops mops = {  }; +struct xlator_dumpops dumpops = { +        .inode      = pl_dump_inode, +};  struct xlator_cbks cbks = {  	.forget      = pl_forget, diff --git a/xlators/protocol/server/src/server-protocol.c b/xlators/protocol/server/src/server-protocol.c index 220f5b3b466..47a6f027736 100644 --- a/xlators/protocol/server/src/server-protocol.c +++ b/xlators/protocol/server/src/server-protocol.c @@ -40,6 +40,7 @@  #include "dict.h"  #include "compat.h"  #include "compat-errno.h" +#include "statedump.h"  static void @@ -7512,7 +7513,80 @@ server_nop_cbk (call_frame_t *frame, void *cookie, xlator_t *this,  	return 0;  } +/* + * server_fd - fdtable dump function for server protocol + * @this: + * + */ +int +server_fd (xlator_t *this) +{ +         server_conf_t        *conf = NULL; + 	 server_connection_t  *trav = NULL; +         char                 key[GF_DUMP_MAX_BUF_LEN]; +         int                  i = 1; +         int                  ret = -1; + 	 +         if (!this) +                 return -1; + 	 +         conf = this->private; +         if (!conf) { + 		gf_log (this->name, GF_LOG_WARNING, + 			"conf null in xlator"); +                return -1; +         } +  +         gf_proc_dump_add_section("xlator.protocol.server.conn"); +          +         ret = pthread_mutex_trylock (&conf->mutex); +         if (ret) {  +                gf_log("", GF_LOG_WARNING, "Unable to dump fdtable" +                " errno: %d", errno); +                return -1; +        } + 	 +         list_for_each_entry (trav, &conf->conns, list) { +                 if (trav->id) { +                         gf_proc_dump_build_key(key,  +                                          "xlator.protocol.server.conn",  +                                          "%d.id", i); +                         gf_proc_dump_write(key, "%s", trav->id); +                 } +                          +                 gf_proc_dump_build_key(key,"xlator.protocol.server.conn", +                                        "%d.ref",i)  +                 gf_proc_dump_write(key, "%d", trav->ref); +                 if (trav->bound_xl) { +                         gf_proc_dump_build_key(key,  +                                          "xlator.protocol.server.conn",  +                                          "%d.bound_xl", i); +                         gf_proc_dump_write(key, "%s", trav->bound_xl->name); +                 } +                          +                 gf_proc_dump_build_key(key,  +                                        "xlator.protocol.server.conn",  +                                         "%d.id", i); +                 fdtable_dump(trav->fdtable,key); +                 i++; +         } + 	pthread_mutex_unlock (&conf->mutex); +  +  + 	return 0; + } + +int +server_priv (xlator_t *this)  +{ +        return 0; +} +int +server_inode (xlator_t *this) +{ +        return 0; +}  static void  get_auth_types (dict_t *this, char *key, data_t *value, void *data)  { @@ -7841,6 +7915,13 @@ struct xlator_fops fops = {  struct xlator_cbks cbks = {  }; +struct xlator_dumpops dumpops = { +        .inode = server_inode, +        .priv  = server_priv, +        .fd    = server_fd, +}; + +  struct volume_options options[] = {   	{ .key   = {"transport-type"},   	  .value = {"tcp", "socket", "ib-verbs", "unix", "ib-sdp",  diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index 4bcea07f9c6..b124d136201 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -45,6 +45,7 @@  #include "compat.h"  #include "byte-order.h"  #include "syscall.h" +#include "statedump.h"  #undef HAVE_SET_FSID  #ifdef HAVE_SET_FSID @@ -3808,6 +3809,45 @@ posix_checksum (call_frame_t *frame, xlator_t *this,          return 0;  } +int32_t +posix_priv (xlator_t *this) +{ +        struct posix_private *priv = NULL; +        char  key_prefix[GF_DUMP_MAX_BUF_LEN]; +        char  key[GF_DUMP_MAX_BUF_LEN]; + +        snprintf(key_prefix, GF_DUMP_MAX_BUF_LEN, "%s.%s", this->type,  +                       this->name); +        gf_proc_dump_add_section(key_prefix); + +        if (!this)  +                return 0; + +        priv = this->private; + +        if (!priv)  +                return 0; + +        gf_proc_dump_build_key(key, key_prefix, "base_path"); +        gf_proc_dump_write(key,"%s", priv->base_path); +        gf_proc_dump_build_key(key, key_prefix, "base_path_length"); +        gf_proc_dump_write(key,"%d", priv->base_path_length); +        gf_proc_dump_build_key(key, key_prefix, "max_read"); +        gf_proc_dump_write(key,"%d", priv->max_read); +        gf_proc_dump_build_key(key, key_prefix, "max_write"); +        gf_proc_dump_write(key,"%d", priv->max_write); +        gf_proc_dump_build_key(key, key_prefix, "stats.nr_files"); +        gf_proc_dump_write(key,"%ld", priv->stats.nr_files); + +        return 0; +} + +int32_t +posix_inode (xlator_t *this) +{ +        return 0; +} +  /**   * notify - when parent sends PARENT_UP, send CHILD_UP event from here   */ @@ -4056,6 +4096,11 @@ fini (xlator_t *this)          return;  } +struct xlator_dumpops dumpops = { +        .priv    = posix_priv, +        .inode   = posix_inode, +}; +  struct xlator_mops mops = {          .stats    = posix_stats,  };  | 
