diff options
author | Pranith Kumar K <pranithk@gluster.com> | 2012-06-04 23:23:45 +0530 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2012-08-30 03:25:50 -0700 |
commit | e908ee20e8a87ba1170f228dd4dd5993f36a0da6 (patch) | |
tree | 3c46db9f78b37ca84a1c6212bb2a2d6fba962020 | |
parent | f382d5c5656301d9b426dc50a95e8c54db42c90e (diff) |
Self-heald: Fix inode leak
RCA:
There is an inode-leak because inode_link returns
linked inode by taking a reference. That needs to be
unreffed.
Fix:
Added the code to perform unrefs. In addition to that
updated the loc inode with the linked-inode because that is
the best practice. The code to update the input inode's
gfid can be removed later, its already removed in master.
Tests:
Checked that opendir comes with an loc with valid inode
Checked that re-opendir happens successfully. Tested index,
full self-heal work fine with the fix.
BUG: 826580
Change-Id: I0c68192ff98f76152ed112b393d497b8fee93355
Signed-off-by: Pranith Kumar K <pranithk@gluster.com>
Reviewed-on: http://review.gluster.org/3518
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Raghavendra Bhat <raghavendra@redhat.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
-rw-r--r-- | xlators/cluster/afr/src/afr-self-heald.c | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/xlators/cluster/afr/src/afr-self-heald.c b/xlators/cluster/afr/src/afr-self-heald.c index f425572b047..5a2172ce9e9 100644 --- a/xlators/cluster/afr/src/afr-self-heald.c +++ b/xlators/cluster/afr/src/afr-self-heald.c @@ -674,6 +674,25 @@ out: } int +_link_inode_update_loc (xlator_t *this, loc_t *loc, struct iatt *iattr) +{ + inode_t *link_inode = NULL; + int ret = -1; + + link_inode = inode_link (loc->inode, NULL, NULL, iattr); + if (link_inode == NULL) { + gf_log (this->name, GF_LOG_ERROR, "inode link failed " + "on the inode (%s)", uuid_utoa (iattr->ia_gfid)); + goto out; + } + inode_unref (loc->inode); + loc->inode = link_inode; + ret = 0; +out: + return ret; +} + +int afr_crawl_build_start_loc (xlator_t *this, afr_crawl_data_t *crawl_data, loc_t *dirloc) { @@ -720,7 +739,9 @@ afr_crawl_build_start_loc (xlator_t *this, afr_crawl_data_t *crawl_data, } goto out; } - inode_link (dirloc->inode, NULL, NULL, &iattr); + ret = _link_inode_update_loc (this, dirloc, &iattr); + if (ret) + goto out; } ret = 0; out: @@ -806,7 +827,6 @@ _process_entries (xlator_t *this, loc_t *parentloc, gf_dirent_t *entries, loc_t entry_loc = {0}; fd_t *fd = NULL; struct iatt iattr = {0}; - inode_t *link_inode = NULL; list_for_each_entry_safe (entry, tmp, &entries->list, list) { if (!_crawl_proceed (this, crawl_data->child, @@ -835,20 +855,17 @@ _process_entries (xlator_t *this, loc_t *parentloc, gf_dirent_t *entries, ret = crawl_data->process_entry (this, crawl_data, entry, &entry_loc, parentloc, &iattr); - if (crawl_data->crawl == INDEX) - continue; - - if (ret || !IA_ISDIR (iattr.ia_type)) + if (ret) continue; - link_inode = inode_link (entry_loc.inode, NULL, NULL, &iattr); - if (link_inode == NULL) { - gf_log (this->name, GF_LOG_ERROR, "inode link failed " - "on the inode (%s)",entry_loc.path); - ret = -1; + ret = _link_inode_update_loc (this, &entry_loc, &iattr); + if (ret) goto out; - } + if (crawl_data->crawl == INDEX) + continue; + if (!IA_ISDIR (iattr.ia_type)) + continue; fd = NULL; ret = afr_crawl_opendir (this, crawl_data, &fd, &entry_loc); if (ret) |