diff options
author | Poornima G <pgurusid@redhat.com> | 2016-03-15 03:14:16 -0400 |
---|---|---|
committer | Raghavendra G <rgowdapp@redhat.com> | 2017-01-18 01:29:45 -0800 |
commit | c9239db7961afd648f1fa3310e5ce9b8281c8ad2 (patch) | |
tree | 26241cfb010b669c6cd325e9d87925f770396577 | |
parent | ff5e91a60887d22934fcb5f8a15dd36019d6e09a (diff) |
inode: Add per xlator ref count for inode
Debugging inode ref leaks is very difficult as there is no info
except for the ref count on the inode. Hence this patch is first step
towards debugging inode ref leaks. With this patch, in the statedump
we get additional info that tells the ref count taken by each xlator
on the inode.
Change-Id: I7802f7e7b13c04eb4d41fdf52d5469fd2c2a185a
BUG: 1325531
Signed-off-by: Poornima G <pgurusid@redhat.com>
Reviewed-on: http://review.gluster.org/13736
CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
Smoke: Gluster Build System <jenkins@build.gluster.org>
-rw-r--r-- | doc/debugging/statedump.md | 3 | ||||
-rw-r--r-- | libglusterfs/src/inode.c | 76 | ||||
-rw-r--r-- | libglusterfs/src/inode.h | 4 |
3 files changed, 67 insertions, 16 deletions
diff --git a/doc/debugging/statedump.md b/doc/debugging/statedump.md index f34a5c3436a..18437f1144c 100644 --- a/doc/debugging/statedump.md +++ b/doc/debugging/statedump.md @@ -215,6 +215,7 @@ nlookup=13 #Number of times lookups happened from the client or from fuse kernel fd-count=4 #Number of fds opened on the inode ref=11 #Number of refs taken on the inode ia_type=1 #Type of the inode. This should be changed to some string :-( +Ref by xl:.patchy-md-cache=11 #Further this there will be a list of xlators, and the ref count taken by each of them on this inode at the time of statedump [conn.1.bound_xl./data/brick01a/homegfs.lru.1] #1st inode in lru list. Note that ref count is zero for these inodes. gfid=5114574e-69bc-412b-9e52-f13ff087c6fc @@ -222,6 +223,8 @@ nlookup=5 fd-count=0 ref=0 ia_type=2 +Ref by xl:.fuse=1 +Ref by xl:.patchy-client-0=-1 ``` ###Inode context For each inode per xlator some context could be stored. This context can also be printed in the statedump. Here is the inode ctx of locks xlator diff --git a/libglusterfs/src/inode.c b/libglusterfs/src/inode.c index 841f0b63f16..d39a2194921 100644 --- a/libglusterfs/src/inode.c +++ b/libglusterfs/src/inode.c @@ -324,7 +324,7 @@ __inode_ctx_free (inode_t *inode) } for (index = 0; index < inode->table->xl->graph->xl_count; index++) { - if (inode->_ctx[index].xl_key) { + if (inode->_ctx[index].value1 || inode->_ctx[index].value2) { xl = (xlator_t *)(long)inode->_ctx[index].xl_key; old_THIS = THIS; THIS = xl; @@ -447,12 +447,40 @@ __inode_retire (inode_t *inode) } +static int +__inode_get_xl_index (inode_t *inode, xlator_t *xlator) +{ + int set_idx = -1; + int index = 0; + + for (index = 0; index < inode->table->ctxcount; index++) { + if (!inode->_ctx[index].xl_key) { + if (set_idx == -1) + set_idx = index; + /* dont break, to check if key already exists + further on */ + } + if (inode->_ctx[index].xl_key == xlator) { + set_idx = index; + break; + } + } + + return set_idx; +} + + static inode_t * __inode_unref (inode_t *inode) { + int index = 0; + xlator_t *this = NULL; + if (!inode) return NULL; + this = THIS; + /* * Root inode should always be in active list of inode table. So unrefs * on root inode are no-ops. @@ -464,6 +492,12 @@ __inode_unref (inode_t *inode) --inode->ref; + index = __inode_get_xl_index (inode, this); + if (index >= 0) { + inode->_ctx[index].xl_key = this; + inode->_ctx[index].ref--; + } + if (!inode->ref) { inode->table->active_size--; @@ -480,9 +514,14 @@ __inode_unref (inode_t *inode) static inode_t * __inode_ref (inode_t *inode) { + int index = 0; + xlator_t *this = NULL; + if (!inode) return NULL; + this = THIS; + if (!inode->ref) { inode->table->lru_size--; __inode_activate (inode); @@ -501,6 +540,12 @@ __inode_ref (inode_t *inode) inode->ref++; + index = __inode_get_xl_index (inode, this); + if (index >= 0) { + inode->_ctx[index].xl_key = this; + inode->_ctx[index].ref++; + } + return inode; } @@ -1935,25 +1980,12 @@ __inode_ctx_set2 (inode_t *inode, xlator_t *xlator, uint64_t *value1_p, uint64_t *value2_p) { int ret = 0; - int index = 0; int set_idx = -1; if (!inode || !xlator || !inode->_ctx) return -1; - for (index = 0; index < inode->table->ctxcount; index++) { - if (!inode->_ctx[index].xl_key) { - if (set_idx == -1) - set_idx = index; - /* dont break, to check if key already exists - further on */ - } - if (inode->_ctx[index].xl_key == xlator) { - set_idx = index; - break; - } - } - + set_idx = __inode_get_xl_index (inode, xlator); if (set_idx == -1) { ret = -1; goto out;; @@ -2313,11 +2345,14 @@ inode_dump (inode_t *inode, char *prefix) int i = 0; fd_t *fd = NULL; struct _inode_ctx *inode_ctx = NULL; - struct list_head fd_list; + struct list_head fd_list; + int ref = 0; + char key[GF_DUMP_MAX_BUF_LEN]; if (!inode) return; + memset(key, 0, sizeof(key)); INIT_LIST_HEAD (&fd_list); ret = TRY_LOCK(&inode->lock); @@ -2342,6 +2377,15 @@ inode_dump (inode_t *inode, char *prefix) for (i = 0; i < inode->table->ctxcount; i++) { inode_ctx[i] = inode->_ctx[i]; + xl = inode_ctx[i].xl_key; + ref = inode_ctx[i].ref; + if (ref != 0 && xl) { + gf_proc_dump_build_key (key, + "ref_by_xl:", + "%s", + xl->name); + gf_proc_dump_write (key, "%d", ref); + } } } diff --git a/libglusterfs/src/inode.h b/libglusterfs/src/inode.h index 5289b15bca6..cdc2095a0e8 100644 --- a/libglusterfs/src/inode.h +++ b/libglusterfs/src/inode.h @@ -81,6 +81,10 @@ struct _inode_ctx { uint64_t value2; void *ptr2; }; + int ref; /* This is for debugging inode ref leaks, + basically helps in identifying the xlator + causing th ref leak, it is printed in + statedump */ }; struct _inode { |