summaryrefslogtreecommitdiffstats
path: root/xlators/protocol/server/src/server3_1-fops.c
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 /xlators/protocol/server/src/server3_1-fops.c
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>
Diffstat (limited to 'xlators/protocol/server/src/server3_1-fops.c')
-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,