}
}
+static void release_tickets(struct fuse *f, fuse_ino_t nodeid,
+ struct node *wnode, int ticket)
+{
+ struct node *node;
+
+ if (wnode) {
+ if (wnode->ticket != ticket)
+ return;
+
+ wnode->ticket = 0;
+ }
+
+ for (node = get_node(f, nodeid);
+ node->nodeid != FUSE_ROOT_ID; node = node->parent) {
+ if (node->ticket != ticket)
+ return;
+ node->ticket = 0;
+ }
+}
+
static int try_get_path(struct fuse *f, fuse_ino_t nodeid, const char *name,
char **path, struct node **wnodep, int ticket)
{
*path = NULL;
+ err = -ENOMEM;
buf = malloc(bufsize);
if (buf == NULL)
- return -ENOMEM;
+ goto out_err;
s = buf + bufsize - 1;
*s = '\0';
out_free:
free(buf);
+ out_err:
+ if (ticket && err != -EAGAIN)
+ release_tickets(f, nodeid, wnode, ticket);
+
return err;
}
if (!err) {
err = try_get_path(f, nodeid2, name2, path2, wnode2, ticket);
if (err) {
- unlock_path(f, nodeid1, wnode1 ? *wnode1 : NULL, NULL,
- ticket);
+ struct node *wn1 = wnode1 ? *wnode1 : NULL;
+
+ unlock_path(f, nodeid1, wn1, NULL, ticket);
free(path1);
+ if (ticket && err != -EAGAIN)
+ release_tickets(f, nodeid1, wn1, ticket);
}
}
return err;