From 59d4142ff1938e3b327fb81bee49402057ae1382 Mon Sep 17 00:00:00 2001 From: Raghavendra G Date: Thu, 8 Oct 2009 06:20:50 +0000 Subject: 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 BUG: 221 (stat prefetch implementation) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=221 --- .../performance/stat-prefetch/src/stat-prefetch.c | 53 +++++++++++++++------- 1 file 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 31f624ad1df..1f309b560a8 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; -- cgit