diff options
author | Raghavendra G <raghavendra@gluster.com> | 2009-10-08 06:20:50 +0000 |
---|---|---|
committer | Anand V. Avati <avati@dev.gluster.com> | 2009-10-09 00:48:11 -0700 |
commit | 59d4142ff1938e3b327fb81bee49402057ae1382 (patch) | |
tree | 655ddf92d530fa5168b7ca7c68fce3b4a8396980 | |
parent | 3949b2828a78e4ecb95edb06f09fb9e7e3e5ce9b (diff) |
performance/stat-prefetch: fix memory leaks
- sp_cache_get_inode uses fd_lookup which internally increases the refcount of
fd by 1. This needs to be unrefed once we get the cache.
- for directories, stat is stored in the inode context in sp_lookup_cbk.
but, while doing so, no check was being done for the presence of context
in inode, resulting in leak of memory equal to sizeof (struct stat) when
multiple lookups happened on the directory.
- path constructed in sp_readdir was not freed.
Signed-off-by: Anand V. Avati <avati@dev.gluster.com>
BUG: 221 (stat prefetch implementation)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=221
-rw-r--r-- | xlators/performance/stat-prefetch/src/stat-prefetch.c | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/xlators/performance/stat-prefetch/src/stat-prefetch.c b/xlators/performance/stat-prefetch/src/stat-prefetch.c index 31f624ad1..1f309b560 100644 --- a/xlators/performance/stat-prefetch/src/stat-prefetch.c +++ b/xlators/performance/stat-prefetch/src/stat-prefetch.c @@ -263,6 +263,8 @@ sp_get_cache_inode (xlator_t *this, inode_t *inode, int32_t pid) } cache = sp_get_cache_fd (this, fd); + + fd_unref (fd); out: return cache; } @@ -365,31 +367,47 @@ sp_lookup_cbk (call_frame_t *frame, void *cookie, xlator_t *this, struct stat *buf, dict_t *dict, struct stat *postparent) { struct stat *stbuf = NULL; - int32_t ret = -1; + int32_t ret = -1; + uint64_t value = 0; if (op_ret == -1) { goto out; } if (S_ISDIR (buf->st_mode)) { - stbuf = CALLOC (1, sizeof (*stbuf)); - if (stbuf == NULL) { - op_ret = -1; - op_errno = ENOMEM; - gf_log (this->name, GF_LOG_ERROR, "out of memory"); - goto out; - } + LOCK (&inode->lock); + { + ret = __inode_ctx_get (inode, this, &value); + if (ret == 0) { + stbuf = (struct stat *)(long)value; + } - memcpy (stbuf, buf, sizeof (*stbuf)); - ret = inode_ctx_put (inode, this, (long)stbuf); - if (ret == -1) { - op_ret = -1; + if (stbuf == NULL) { + stbuf = CALLOC (1, sizeof (*stbuf)); + if (stbuf == NULL) { + op_ret = -1; + op_errno = ENOMEM; + gf_log (this->name, GF_LOG_ERROR, + "out of memory"); + goto unlock; + } - /* FIXME: EINVAL is not correct */ - op_errno = EINVAL; - FREE (stbuf); - goto out; + ret = __inode_ctx_put (inode, this, + (long)stbuf); + if (ret == -1) { + op_ret = -1; + + /* FIXME: EINVAL is not correct */ + op_errno = EINVAL; + FREE (stbuf); + goto unlock; + } + } + + memcpy (stbuf, buf, sizeof (*stbuf)); } + unlock: + UNLOCK (&inode->lock); } out: @@ -649,6 +667,9 @@ sp_readdir (call_frame_t *frame, xlator_t *this, fd_t *fd, size_t size, } ret = sp_cache_remove_parent_entry (frame, this, path); + + FREE (path); + if (ret < 0) { errno = -ret; goto unwind; |