diff options
Diffstat (limited to 'libglusterfs/src')
| -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 | 
11 files changed, 740 insertions, 7 deletions
diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am index 7698661fa..a3fb923ca 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 8f7616929..62536fc55 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 9796071d8..138e30068 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 6d6fca133..e9408f86b 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 d17c1db48..de95da324 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 000000000..453248479 --- /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 e7c1cbd15..942972556 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 000000000..6839c28f6 --- /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 000000000..9ac50ec0c --- /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 a3f8ea8fc..def1ad1df 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 e8fc9d250..2e815af91 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);  | 
