summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaghavendra Bhat <raghavendrabhat@gluster.com>2012-03-06 14:35:45 +0530
committerAnand Avati <avati@redhat.com>2012-03-18 01:00:01 -0700
commit6bf0a809c99ec33fee73e6ebebb58baa2614f977 (patch)
treeb98ac8abdb614d3baa47eb3730a2a0c9ff2c6cda
parent93022c0cc6c22b3a30ded3e109a3fe0a0dce8ca0 (diff)
protocol/server: send forget on the renamed inode
If rename is given on a file "a" to "b" ("b" is already existing file), then after rename, the inode for "b" would still be in the inode table and would not get forget (for fuse client, the fuse kernel module would send, but on server forget will not come on that inode), thus leading to inode leak even when the mount point is empty. To avoid that before doing inode rename, unlink the previous inode that "b" is pointing to and send forget on that, if "b" is the last dentry for that inode. Change-Id: Ie4dcc39ea190ee8f28029b4d7661df576d9cf319 BUG: 799833 Signed-off-by: Raghavendra Bhat <raghavendrabhat@gluster.com> Reviewed-on: http://review.gluster.com/2874 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Amar Tumballi <amarts@redhat.com> Reviewed-by: Anand Avati <avati@redhat.com>
-rw-r--r--xlators/protocol/server/src/server3_1-fops.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/xlators/protocol/server/src/server3_1-fops.c b/xlators/protocol/server/src/server3_1-fops.c
index d44ee1cf7..ef9a98f38 100644
--- a/xlators/protocol/server/src/server3_1-fops.c
+++ b/xlators/protocol/server/src/server3_1-fops.c
@@ -414,6 +414,10 @@ server_rmdir_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
state->loc.name);
parent = inode_parent (state->loc.inode, 0, NULL);
if (parent)
+ /* parent should not be found for directories after
+ * inode_unlink, since directories cannot have
+ * hardlinks.
+ */
inode_unref (parent);
else
inode_forget (state->loc.inode, 0);
@@ -830,6 +834,8 @@ server_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
gfs3_rename_rsp rsp = {0,};
server_state_t *state = NULL;
rpcsvc_request_t *req = NULL;
+ inode_t *tmp_inode = NULL;
+ inode_t *tmp_parent = NULL;
req = frame->local;
@@ -846,6 +852,28 @@ server_rename_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
"%"PRId64": RENAME_CBK %s ==> %s",
frame->root->unique, state->loc.name, state->loc2.name);
+ /* Before renaming the inode, we have to get the inode for the
+ * destination entry (i.e. inode with state->loc2.parent as
+ * parent and state->loc2.name as name). If it exists, then
+ * unlink that inode, and send forget on that inode if the
+ * unlinked entry is the last entry. In case of fuse client
+ * the fuse kernel module itself sends the forget on the
+ * unlinked inode.
+ */
+ tmp_inode = inode_grep (state->loc.inode->table,
+ state->loc2.parent, state->loc2.name);
+ if (tmp_inode) {
+ inode_unlink (tmp_inode, state->loc2.parent,
+ state->loc2.name);
+ tmp_parent = inode_parent (tmp_inode, 0, NULL);
+ if (tmp_parent)
+ inode_unref (tmp_parent);
+ else
+ inode_forget (tmp_inode, 0);
+
+ inode_unref (tmp_inode);
+ }
+
inode_rename (state->itable,
state->loc.parent, state->loc.name,
state->loc2.parent, state->loc2.name,