aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2012-08-14 11:18:07 +0200
committerMiklos Szeredi <mszeredi@suse.cz>2012-08-14 11:18:07 +0200
commit1061a0a2d90148bd2e7f32e1e694399db2dbe087 (patch)
tree7e720dfbe3e7a42dd35d8aa2734395c206ce4b12
parentefeac22bfa65c845c04adb5e70e6de33b0104fa3 (diff)
downloadandroid_external_fuse-1061a0a2d90148bd2e7f32e1e694399db2dbe087.tar.gz
android_external_fuse-1061a0a2d90148bd2e7f32e1e694399db2dbe087.tar.bz2
android_external_fuse-1061a0a2d90148bd2e7f32e1e694399db2dbe087.zip
Fix "fuse internal error: node NNN not found"
Commit 4dc7e675bb (Don't unhash name in FORGET) broke the forget logic in a subtle way, resulting in "fuse internal error: node NNN not found" and causing the filesystem daemon to abort. Fix by incrementing the node refcount if nlookup goes from zero to one. Reported by Kyle Lippincott
-rw-r--r--ChangeLog8
-rw-r--r--lib/fuse.c16
2 files changed, 20 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 4660598..6631784 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2012-08-14 Miklos Szeredi <miklos@szeredi.hu>
+
+ * Not unhashing the name in forget (commit on 2011-12-09) broke
+ the forget logic in a subtle way, resulting in "fuse internal
+ error: node NNN not found" and causing the filesystem daemon to
+ abort. Fix by incrementing the node refcount if nlookup goes from
+ zero to one. Reported by Kyle Lippincott
+
2012-08-13 Miklos Szeredi <miklos@szeredi.hu>
* Fix linking against GNU libiconv. Patch by Natanael Copa
diff --git a/lib/fuse.c b/lib/fuse.c
index 3c7f642..f801f84 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -816,6 +816,13 @@ static struct node *lookup_node(struct fuse *f, fuse_ino_t parent,
return NULL;
}
+static void inc_nlookup(struct node *node)
+{
+ if (!node->nlookup)
+ node->refctr++;
+ node->nlookup++;
+}
+
static struct node *find_node(struct fuse *f, fuse_ino_t parent,
const char *name)
{
@@ -831,15 +838,16 @@ static struct node *find_node(struct fuse *f, fuse_ino_t parent,
if (node == NULL)
goto out_err;
- if (f->conf.remember)
- node->nlookup = 1;
- node->refctr = 1;
+ node->refctr = 0;
node->nodeid = next_id(f);
node->generation = f->generation;
node->open_count = 0;
node->is_hidden = 0;
node->treelock = 0;
node->ticket = 0;
+ if (f->conf.remember)
+ inc_nlookup(node);
+
if (hash_name(f, node, parent, name) == -1) {
free_node(f, node);
node = NULL;
@@ -853,7 +861,7 @@ static struct node *find_node(struct fuse *f, fuse_ino_t parent,
} else if (lru_enabled(f) && node->nlookup == 1) {
remove_node_lru(node);
}
- node->nlookup ++;
+ inc_nlookup(node);
out_err:
pthread_mutex_unlock(&f->lock);
return node;