summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2012-08-14 14:03:10 +0200
committerMiklos Szeredi <mszeredi@suse.cz>2012-08-14 14:03:10 +0200
commit07b4946b5bee7f60d533b8b21c1eea16dbb86917 (patch)
tree8964f5acb853ac60f276841a5a8a65c43c0f8145
parent5957ea2fd952cc7158f5632655d706abfa789e95 (diff)
parentfdff523325bf49dc1cb9b62787dcf4ae22898d0f (diff)
downloadfuse-07b4946b5bee7f60d533b8b21c1eea16dbb86917.tar.gz
Merge branch 'fuse_2_9_bugfix'
-rw-r--r--ChangeLog8
-rw-r--r--lib/fuse.c28
2 files changed, 23 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index f2582bc..24210cf 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 9294822..86c8547 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -321,12 +321,12 @@ static void list_add(struct list_head *new, struct list_head *prev,
prev->next = new;
}
-static void list_add_head(struct list_head *new, struct list_head *head)
+static inline void list_add_head(struct list_head *new, struct list_head *head)
{
list_add(new, head, head->next);
}
-static void list_add_tail(struct list_head *new, struct list_head *head)
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
list_add(new, head->prev, head);
}
@@ -419,6 +419,7 @@ static struct node *alloc_node(struct fuse *f)
list_del(&slab->list);
list_add_tail(&slab->list, &f->full_slabs);
}
+ memset(node, 0, sizeof(struct node));
return (struct node *) node;
}
@@ -812,6 +813,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)
{
@@ -827,15 +835,11 @@ 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->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;
@@ -849,7 +853,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;
@@ -4494,9 +4498,7 @@ struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
root->parent = NULL;
root->nodeid = FUSE_ROOT_ID;
- root->generation = 0;
- root->refctr = 1;
- root->nlookup = 1;
+ inc_nlookup(root);
hash_id(f, root);
return f;