summaryrefslogtreecommitdiffstats
path: root/xlators/mount/fuse
diff options
context:
space:
mode:
authorXavier Hernandez <xhernandez@datalab.es>2016-01-30 22:35:19 +0100
committerKaleb KEITHLEY <kkeithle@redhat.com>2016-02-03 23:57:39 -0800
commitbb1bc854b85ed2e3f51da3a82f56c154ca348e33 (patch)
tree465a56b26c757f7ba9c661be75a9c163f296c4db /xlators/mount/fuse
parentb8106d1127f034ffa88b5dd322c23a10e023b9b6 (diff)
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 kernel to send 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: I31901af36ab7b4cdc3e6fa2f30a0263a1a2daef8 Signed-off-by: Xavier Hernandez <xhernandez@datalab.es> Reviewed-on: http://review.gluster.org/13327 Smoke: Gluster Build System <jenkins@build.gluster.com> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Kaleb KEITHLEY <kkeithle@redhat.com>
Diffstat (limited to 'xlators/mount/fuse')
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c46
1 files changed, 27 insertions, 19 deletions
diff --git a/xlators/mount/fuse/src/fuse-bridge.c b/xlators/mount/fuse/src/fuse-bridge.c
index cc3948680e9..dd8ac1b1c74 100644
--- a/xlators/mount/fuse/src/fuse-bridge.c
+++ b/xlators/mount/fuse/src/fuse-bridge.c
@@ -224,11 +224,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);
@@ -238,8 +243,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);
@@ -2810,13 +2813,13 @@ fuse_readdirp_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
if (!linked_inode)
goto next_entry;
- inode_lookup (linked_inode);
-
feo->nodeid = inode_to_fuse_nodeid (linked_inode);
if (!((strcmp (entry->d_name, ".") == 0) ||
- (strcmp (entry->d_name, "..") == 0)))
+ (strcmp (entry->d_name, "..") == 0))) {
+ inode_lookup (linked_inode);
inode_set_need_lookup (linked_inode, this);
+ }
inode_unref (linked_inode);
@@ -4140,7 +4143,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;
@@ -4154,7 +4157,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;
@@ -4170,20 +4173,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);
@@ -4191,7 +4196,10 @@ fuse_first_lookup (xlator_t *this)
frame->local = NULL;
STACK_DESTROY (frame->root);
- return 0;
+out:
+ inode_unref(loc.inode);
+
+ return ret;
}