From bacdf9335bc674d87ca408feafa3515fb00f47b2 Mon Sep 17 00:00:00 2001 From: Xavier Hernandez Date: Sat, 30 Jan 2016 22:35:19 +0100 Subject: fuse: fix inode and dentry leaks When a readdirp was executed, the nlookup count for each inode of the returned entries was incremented. However the kernel does not increment the counter for '.' and '..' entries. This caused that kernel sent forgets with a counter smaller than the inode's current value. This prevented these inodes to be retired when ref count was 0. Change-Id: I36f3736c86d1cc20adabbbc133ce4edeff62db78 Signed-off-by: Xavier Hernandez Reviewed-on: http://review.gluster.org/13324 Smoke: Gluster Build System Reviewed-by: Raghavendra Bhat Tested-by: Kaleb KEITHLEY CentOS-regression: Gluster Build System NetBSD-regression: NetBSD Build System Reviewed-by: Kaleb KEITHLEY --- xlators/mount/fuse/src/fuse-bridge.c | 51 ++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 22 deletions(-) (limited to 'xlators/mount/fuse/src') diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c index bd7d5adf9db..87db40fd8c9 100644 --- a/xlators/mount/fuse/src/fuse-bridge.c +++ b/xlators/mount/fuse/src/fuse-bridge.c @@ -223,11 +223,16 @@ fuse_invalidate_entry (xlator_t *this, uint64_t fuse_ino) if (!priv->reverse_fuse_thread_started) return; + inode = fuse_ino_to_inode(fuse_ino, this); + if (inode == NULL) { + return; + } + list_for_each_entry (dentry, &inode->dentry_list, inode_list) { node = GF_CALLOC (1, sizeof (*node), gf_fuse_mt_invalidate_node_t); if (node == NULL) - return; + break; INIT_LIST_HEAD (&node->next); @@ -237,8 +242,6 @@ fuse_invalidate_entry (xlator_t *this, uint64_t fuse_ino) fouh->unique = 0; fouh->error = FUSE_NOTIFY_INVAL_ENTRY; - inode = fuse_ino_to_inode (fuse_ino, this); - nlen = strlen (dentry->name); fouh->len = sizeof (*fouh) + sizeof (*fnieo) + nlen + 1; fnieo->parent = inode_to_fuse_nodeid (dentry->parent); @@ -428,9 +431,6 @@ fuse_entry_cbk (call_frame_t *frame, void *cookie, xlator_t *this, linked_inode = inode_link (inode, state->loc.parent, state->loc.name, buf); - if (linked_inode != inode) { - } - inode_lookup (linked_inode); feo.nodeid = inode_to_fuse_nodeid (linked_inode); @@ -2804,12 +2804,14 @@ fuse_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this, if (!linked_inode) goto next_entry; - inode_lookup (linked_inode); + if ((strcmp(entry->d_name, ".") != 0) && + (strcmp(entry->d_name, "..") != 0)) { + inode_lookup (linked_inode); + inode_set_need_lookup (linked_inode, this); + } feo->nodeid = inode_to_fuse_nodeid (linked_inode); - inode_set_need_lookup (linked_inode, this); - inode_unref (linked_inode); feo->entry_valid = @@ -4132,7 +4134,7 @@ fuse_first_lookup (xlator_t *this) dict_t *dict = NULL; struct fuse_first_lookup stub; uuid_t gfid; - int ret; + int ret = -1; priv = this->private; @@ -4146,7 +4148,7 @@ fuse_first_lookup (xlator_t *this) frame = create_frame (this, this->ctx->pool); if (!frame) { gf_log ("fuse", GF_LOG_ERROR, "failed to create frame"); - return -1; + goto out; } frame->root->type = GF_OP_TYPE_FOP; @@ -4162,20 +4164,22 @@ fuse_first_lookup (xlator_t *this) memset (gfid, 0, 16); gfid[15] = 1; ret = dict_set_static_bin (dict, "gfid-req", gfid, 16); - if (ret) + if (ret) { gf_log (xl->name, GF_LOG_ERROR, "failed to set 'gfid-req'"); + } else { + STACK_WIND (frame, fuse_first_lookup_cbk, xl, xl->fops->lookup, + &loc, dict); - STACK_WIND (frame, fuse_first_lookup_cbk, xl, xl->fops->lookup, - &loc, dict); - dict_unref (dict); - - pthread_mutex_lock (&stub.mutex); - { - while (!stub.fin) { - pthread_cond_wait (&stub.cond, &stub.mutex); + pthread_mutex_lock (&stub.mutex); + { + while (!stub.fin) { + pthread_cond_wait (&stub.cond, &stub.mutex); + } } + pthread_mutex_unlock (&stub.mutex); } - pthread_mutex_unlock (&stub.mutex); + + dict_unref (dict); pthread_mutex_destroy (&stub.mutex); pthread_cond_destroy (&stub.cond); @@ -4183,7 +4187,10 @@ fuse_first_lookup (xlator_t *this) frame->local = NULL; STACK_DESTROY (frame->root); - return 0; +out: + inode_unref(loc.inode); + + return ret; } -- cgit