Fix "fuse internal error: node NNN not found"
authorMiklos Szeredi <mszeredi@suse.cz>
Tue, 14 Aug 2012 09:18:07 +0000 (11:18 +0200)
committerMiklos Szeredi <mszeredi@suse.cz>
Tue, 14 Aug 2012 09:18:07 +0000 (11:18 +0200)
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

ChangeLog
lib/fuse.c

index 4660598903b36f1c57cbdfca60fde7ab5dcdf86d..66317845c9d6f5098f5e9446ca65d472a774e2a7 100644 (file)
--- 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
index 3c7f6425a3ec1de41bf83307686e92a654ee6c1a..f801f84524fcb1cbe2b090bc4d4575b6c33b3e28 100644 (file)
@@ -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;