fix
authorMiklos Szeredi <miklos@szeredi.hu>
Tue, 12 Jul 2005 13:23:53 +0000 (13:23 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Tue, 12 Jul 2005 13:23:53 +0000 (13:23 +0000)
ChangeLog
include/fuse_lowlevel.h
lib/fuse_lowlevel.c
lib/fuse_mt.c

index f820dd407f6d044e70833928f8075bd5e5dff35b..ee8741c474f83c8c0c44880d15cfa5ec14717051 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2005-07-12  Miklos Szeredi <miklos@szeredi.hu>
+
+       * lib: don't block signals in worker threads.  Problem noticed by
+       Usarin Heininga
+
 2005-07-07  Miklos Szeredi <miklos@szeredi.hu>
 
        * lib: don't allow both 'allow_other' and 'allow_root' options to
index e90cb8483e854205cb3c4d0d7b08dec09be33fe9..673493e46abbbf5ec73746b0628c54423673b260 100644 (file)
@@ -6,13 +6,31 @@
     See the file COPYING.LIB.
 */
 
+#ifndef _FUSE_LOWLEVEL_H_
+#define _FUSE_LOWLEVEL_H_
+
 /* ----------------------------------------------------------- *
  * Low level API                                               *
  * ----------------------------------------------------------- */
 
+#include <fuse_common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef unsigned long fuse_ino_t;
 typedef struct fuse_req *fuse_req_t;
 
+struct fuse_entry_param {
+    fuse_ino_t ino;
+    unsigned long generation;
+    const struct stat *attr;
+    double attr_timeout;
+    double entry_timeout;
+    unsigned int direct_io : 1;
+};
+
 /* 'to_set' flags in setattr */
 #define FUSE_SET_ATTR_MODE     (1 << 0)
 #define FUSE_SET_ATTR_UID      (1 << 1)
@@ -26,6 +44,8 @@ struct fuse_lowlevel_operations {
     void (*lookup)  (fuse_req_t req, fuse_ino_t parent, const char *name);
     void (*forget)  (fuse_req_t req, fuse_ino_t ino);
     void (*getattr) (fuse_req_t req, fuse_ino_t ino);
+    void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
+                     int to_set);
     void (*readlink)(fuse_req_t req, fuse_ino_t ino);
     void (*mknod)   (fuse_req_t req, fuse_ino_t parent, const char *name,
                      mode_t mode, dev_t rdev);
@@ -39,8 +59,6 @@ struct fuse_lowlevel_operations {
                      fuse_ino_t newparent, const char *newname);
     void (*link)    (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
                      const char *newname);
-    void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
-                     int to_set);
     void (*open)    (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f);
     void (*read)    (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
                      struct fuse_file_info *f);
@@ -48,13 +66,15 @@ struct fuse_lowlevel_operations {
                      size_t size, off_t off, struct fuse_file_info *f);
     void (*flush)   (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f);
     void (*release) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f);
-    void (*fsync)   (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f);
+    void (*fsync)   (fuse_req_t req, fuse_ino_t ino, int datasync,
+                     struct fuse_file_info *f);
     void (*opendir) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f);
     void (*readdir)  (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
                      struct fuse_file_info *f);
     void (*releasedir) (fuse_req_t req, fuse_ino_t ino,
                         struct fuse_file_info *f);
-    void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f);
+    void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, int datasync,
+                      struct fuse_file_info *f);
     void (*statfs)  (fuse_req_t req, fuse_ino_t ino);
     void (*setxattr)(fuse_req_t req, fuse_ino_t ino, const char *name,
                      const char *value, size_t size, int flags);
@@ -71,18 +91,20 @@ int fuse_reply_err(fuse_req_t req, int err);
 int fuse_reply_ok(fuse_req_t req);
 
 /* lookup, mknod, mkdir, symlink, link */
-int fuse_reply_entry(fuse_req_t req, fuse_ino_t ino, unsigned long generation,
-                     const struct stat *attr, double attr_timeout,
-                     double entry_timeout);
+int fuse_reply_entry(fuse_req_t req, struct fuse_entry_param *e);
 
 /* getattr, setattr */
 int fuse_reply_attr(fuse_req_t req, int struct stat *attr, double attr_timeout);
 /* readlink */
 int fuse_reply_readlink(fuse_req_t req, const char *link);
 
-/* open, write, flush, fsync, opendir, fsyncdir */
+/* open, flush, fsync, opendir, fsyncdir */
 int fuse_reply_file_info(fuse_req_t req, const struct fuse_file_info *f);
 
+/* write */
+int fuse_reply_write(fuse_req_t req, size_t count,
+                         const struct fuse_file_info *f);
+
 /* read, readdir */
 int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size,
                     const struct fuse_file_info *f);
@@ -97,5 +119,11 @@ int fuse_reply_xattr(fuse_req_t req, const char *buf, size_t size);
 size_t fuse_dirent_size(size_t namelen);
 
 /* add a directory entry to the buffer */
-int fuse_add_dirent(char *buf, const char *name, const struct stat *stat,
-                    off_t off);
+void fuse_add_dirent(char *buf, const char *name, const struct stat *stat,
+                     off_t off);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FUSE_LOWLEVEL_H_ */
index c5e1bf79404bca2f8df803019734158e98d768c8..b21a8fe3502ce149d585e1087393a8605315a969 100644 (file)
 #include <sys/param.h>
 #include <sys/uio.h>
 
-/* FUSE flags: */
-
-/** Enable debuging output */
-#define FUSE_DEBUG       (1 << 1)
-
-/** If a file is removed but it's still open, don't hide the file but
-    remove it immediately */
-#define FUSE_HARD_REMOVE (1 << 2)
-
-/** Use st_ino field in getattr instead of generating inode numbers  */
-#define FUSE_USE_INO     (1 << 3)
-
-/** Only allow root or the owner to access the filesystem */
-#define FUSE_ALLOW_ROOT  (1 << 4)
-
-/** Make a best effort to fill in inode number in a readdir **/
-#define FUSE_READDIR_INO (1 << 5)
-
-/** Ignore file mode supplied by the filesystem, and create one based
-    on the 'umask' option */
-#define FUSE_SET_MODE (1 << 6)
-
-/** Ignore st_uid supplied by the filesystem and set it based on the
-    'uid' option*/
-#define FUSE_SET_UID (1 << 7)
-
-/** Ignore st_gid supplied by the filesystem and set it based on the
-    'gid' option*/
-#define FUSE_SET_GID (1 << 8)
-
+#define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
 
 struct fuse_ll {
-    int flags;
+    unsigned int debug : 1;
+    unsigned int allow_root : 1;
     int fd;
     struct fuse_lowlevel_operations op;
     volatile int exited;
@@ -63,9 +35,6 @@ struct fuse_ll {
     int major;
     int minor;
     uid_t owner;
-    uid_t uid;
-    gid_t gid;
-    mode_t umask;
 };
 
 struct fuse_cmd {
@@ -108,17 +77,13 @@ static const char *opname(enum fuse_opcode opcode)
     }
 }
 
-
-static void convert_stat(struct fuse_ll *f, nodeid_t nodeid, struct stat *stbuf,
-                         struct fuse_attr *attr)
+static void convert_stat(struct stat *stbuf, struct fuse_attr *attr)
 {
-    attr->ino       = (f->flags & FUSE_USE_INO) ? stbuf->st_ino : nodeid;
+    attr->ino       = stbuf->st_ino;
     attr->mode      = stbuf->st_mode;
-    if (f->flags & FUSE_SET_MODE)
-        attr->mode = (attr->mode & S_IFMT) | (0777 & ~f->umask);
     attr->nlink     = stbuf->st_nlink;
-    attr->uid       = (f->flags & FUSE_SET_UID) ? f->uid : stbuf->st_uid;
-    attr->gid       = (f->flags & FUSE_SET_GID) ? f->gid : stbuf->st_gid;
+    attr->uid       = stbuf->st_uid;
+    attr->gid       = stbuf->st_gid;
     attr->rdev      = stbuf->st_rdev;
     attr->size      = stbuf->st_size;
     attr->blocks    = stbuf->st_blocks;
@@ -196,705 +161,294 @@ static int send_reply(struct fuse_ll *f, struct fuse_in_header *in, int error,
     return send_reply_raw(f, iov, count);
 }
 
-static void do_lookup(struct fuse_ll *f, struct fuse_in_header *in, char *name)
-{
-    int res;
-    int res2;
-    char *path;
-    struct fuse_entry_out arg;
-
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path_name(f, in->nodeid, name);
-    if (path != NULL) {
-        if (f->flags & FUSE_DEBUG) {
-            printf("LOOKUP %s\n", path);
-            fflush(stdout);
-        }
-        res = -ENOSYS;
-        if (f->op.getattr)
-            res = lookup_path(f, in->nodeid, in->unique, name, path, &arg);
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    res2 = send_reply(f, in, res, &arg, sizeof(arg));
-    if (res == 0 && res2 == -ENOENT)
-        cancel_lookup(f, arg.nodeid, in->unique);
-}
-
-static void do_forget(struct fuse_ll *f, struct fuse_in_header *in,
-                      struct fuse_forget_in *arg)
+size_t fuse_dirent_size(size_t namelen)
 {
-    if (f->flags & FUSE_DEBUG) {
-        printf("FORGET %lu/%llu\n", (unsigned long) in->nodeid,
-               arg->nlookup);
-        fflush(stdout);
-    }
-    if (f->major <= 6)
-        forget_node_old(f, in->nodeid, arg->nlookup);
-    else
-        forget_node(f, in->nodeid, arg->nlookup);
+    return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen);
 }
 
-static void do_getattr(struct fuse_ll *f, struct fuse_in_header *in)
+void fuse_add_dirent(char *buf, const char *name, const struct stat *stat,
+                     off_t off)
 {
-    int res;
-    char *path;
-    struct stat buf;
-    struct fuse_attr_out arg;
-
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path(f, in->nodeid);
-    if (path != NULL) {
-        res = -ENOSYS;
-        if (f->op.getattr)
-            res = f->op.getattr(path, &buf);
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-
-    if (res == 0) {
-        memset(&arg, 0, sizeof(struct fuse_attr_out));
-        arg.attr_valid = ATTR_REVALIDATE_TIME;
-        arg.attr_valid_nsec = 0;
-        convert_stat(f, in->nodeid, &buf, &arg.attr);
-    }
+    unsigned namelen = strlen(name);
+    unsigned entlen = FUSE_NAME_OFFSET + namelen;
+    unsigned entsize = fuse_dirent_size(namelen);
+    unsigned padlen = entsize - entlen;
+    struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
+
+    dirent->ino = stat->st_ino;
+    dirent->off = off;
+    dirent->namelen = namelen;
+    dirent->type = (stat->st_mode & 0170000) >> 12;
+    strncpy(dirent->name, name, namelen);
+    if (padlen)
+        memset(buf + entlen, 0, padlen);
 
-    send_reply(f, in, res, &arg, sizeof(arg));
+    return 0;
 }
 
-static int do_chmod(struct fuse_ll *f, const char *path, struct fuse_attr *attr)
+static void convert_statfs(struct statfs *statfs, struct fuse_kstatfs *kstatfs)
 {
-    int res;
-
-    res = -ENOSYS;
-    if (f->op.chmod)
-        res = f->op.chmod(path, attr->mode);
-
-    return res;
+    kstatfs->bsize     = statfs->f_bsize;
+    kstatfs->blocks    = statfs->f_blocks;
+    kstatfs->bfree     = statfs->f_bfree;
+    kstatfs->bavail    = statfs->f_bavail;
+    kstatfs->files     = statfs->f_files;
+    kstatfs->ffree     = statfs->f_ffree;
+    kstatfs->namelen   = statfs->f_namelen;
 }
 
-static int do_chown(struct fuse_ll *f, const char *path, struct fuse_attr *attr,
-                    int valid)
+static void do_lookup(fuse_req_t req, fuse_ino_t nodeid, char *name)
 {
-    int res;
-    uid_t uid = (valid & FATTR_UID) ? attr->uid : (uid_t) -1;
-    gid_t gid = (valid & FATTR_GID) ? attr->gid : (gid_t) -1;
-
-    res = -ENOSYS;
-    if (f->op.chown)
-        res = f->op.chown(path, uid, gid);
-
-    return res;
+    if (req->f->op.lookup)
+        req->f->op.lookup(req, nodeid, name);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static int do_truncate(struct fuse_ll *f, const char *path,
-                       struct fuse_attr *attr)
+static void do_forget(fuse_req_t req, fuse_ino_t nodeid)
 {
-    int res;
-
-    res = -ENOSYS;
-    if (f->op.truncate)
-        res = f->op.truncate(path, attr->size);
-
-    return res;
+    if (req->f->op.forget)
+        req->f->op.forget(req, nodeid);
 }
 
-static int do_utime(struct fuse_ll *f, const char *path, struct fuse_attr *attr)
+static void do_getattr(fuse_req_t req, fuse_ino_t nodeid)
 {
-    int res;
-    struct utimbuf buf;
-    buf.actime = attr->atime;
-    buf.modtime = attr->mtime;
-    res = -ENOSYS;
-    if (f->op.utime)
-        res = f->op.utime(path, &buf);
-
-    return res;
+    if (req->f->op.getattr)
+        req->f->op.getattr(req, nodeid);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_setattr(struct fuse_ll *f, struct fuse_in_header *in,
+static void do_setattr(fuse_req_t req, fuse_ino_t nodeid,
                        struct fuse_setattr_in *arg)
 {
-    int res;
-    char *path;
-    int valid = arg->valid;
-    struct fuse_attr *attr = MEMBER_COMPAT(f, arg, attr, fuse_setattr_in);
-    struct fuse_attr_out outarg;
-
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path(f, in->nodeid);
-    if (path != NULL) {
-        res = -ENOSYS;
-        if (f->op.getattr) {
-            res = 0;
-            if (!res && (valid & FATTR_MODE))
-                res = do_chmod(f, path, attr);
-            if (!res && (valid & (FATTR_UID | FATTR_GID)))
-                res = do_chown(f, path, attr, valid);
-            if (!res && (valid & FATTR_SIZE))
-                res = do_truncate(f, path, attr);
-            if (!res && (valid & (FATTR_ATIME | FATTR_MTIME)) ==
-               (FATTR_ATIME | FATTR_MTIME))
-                res = do_utime(f, path, attr);
-            if (!res) {
-                struct stat buf;
-                res = f->op.getattr(path, &buf);
-                if (!res) {
-                    memset(&outarg, 0, sizeof(struct fuse_attr_out));
-                    outarg.attr_valid = ATTR_REVALIDATE_TIME;
-                    outarg.attr_valid_nsec = 0;
-                    convert_stat(f, in->nodeid, &buf, &outarg.attr);
-                }
-            }
-        }
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    send_reply(f, in, res, &outarg, sizeof(outarg));
+    if (req->f->op.setattr)
+        req->f->op.setattr(req, nodeid, &arg->attr, arg->valid);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_readlink(struct fuse_ll *f, struct fuse_in_header *in)
+static void do_readlink(fuse_req_t req, fuse_ino_t nodeid)
 {
-    int res;
-    char link[PATH_MAX + 1];
-    char *path;
-
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path(f, in->nodeid);
-    if (path != NULL) {
-        res = -ENOSYS;
-        if (f->op.readlink)
-            res = f->op.readlink(path, link, sizeof(link));
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    link[PATH_MAX] = '\0';
-    send_reply(f, in, res, link, res == 0 ? strlen(link) : 0);
+    if (req->f->op.readlink)
+        req->f->op.readlink(req, nodeid);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_mknod(struct fuse_ll *f, struct fuse_in_header *in,
-                     struct fuse_mknod_in *inarg)
+static void do_mknod(fuse_req_t req, fuse_ino_t nodeid,
+                     struct fuse_mknod_in *arg)
 {
-    int res;
-    int res2;
-    char *path;
-    char *name = PARAM(inarg);
-    struct fuse_entry_out outarg;
-
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path_name(f, in->nodeid, name);
-    if (path != NULL) {
-        if (f->flags & FUSE_DEBUG) {
-            printf("MKNOD %s\n", path);
-            fflush(stdout);
-        }
-        res = -ENOSYS;
-        if (f->op.mknod && f->op.getattr) {
-            res = f->op.mknod(path, inarg->mode, inarg->rdev);
-            if (res == 0)
-                res = lookup_path(f, in->nodeid, in->unique, name, path, &outarg);
-        }
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
-    if (res == 0 && res2 == -ENOENT)
-        cancel_lookup(f, outarg.nodeid, in->unique);
+    if (req->f->op.mknod)
+        req->f->op.mknod(req, nodeid, PARAM(arg), arg->mode, arg->rdev);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_mkdir(struct fuse_ll *f, struct fuse_in_header *in,
-                     struct fuse_mkdir_in *inarg)
+static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid,
+                     struct fuse_mkdir_in *arg)
 {
-    int res;
-    int res2;
-    char *path;
-    char *name = PARAM_COMPAT(f, inarg, fuse_mkdir_in);
-    struct fuse_entry_out outarg;
-
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path_name(f, in->nodeid, name);
-    if (path != NULL) {
-        if (f->flags & FUSE_DEBUG) {
-            printf("MKDIR %s\n", path);
-            fflush(stdout);
-        }
-        res = -ENOSYS;
-        if (f->op.mkdir && f->op.getattr) {
-            res = f->op.mkdir(path, inarg->mode);
-            if (res == 0)
-                res = lookup_path(f, in->nodeid, in->unique, name, path, &outarg);
-        }
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
-    if (res == 0 && res2 == -ENOENT)
-        cancel_lookup(f, outarg.nodeid, in->unique);
+    if (req->f->op.mkdir)
+        req->f->op.mkdir(req, nodeid, PARAM(arg), arg->mode);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_unlink(struct fuse_ll *f, struct fuse_in_header *in, char *name)
+static void do_unlink(fuse_req_t req, fuse_ino_t nodeid, char *name)
 {
-    int res;
-    char *path;
-
-    res = -ENOENT;
-    pthread_rwlock_wrlock(&f->tree_lock);
-    path = get_path_name(f, in->nodeid, name);
-    if (path != NULL) {
-        if (f->flags & FUSE_DEBUG) {
-            printf("UNLINK %s\n", path);
-            fflush(stdout);
-        }
-        res = -ENOSYS;
-        if (f->op.unlink) {
-            if (!(f->flags & FUSE_HARD_REMOVE) && is_open(f, in->nodeid, name))
-                res = hide_node(f, path, in->nodeid, name);
-            else {
-                res = f->op.unlink(path);
-                if (res == 0)
-                    remove_node(f, in->nodeid, name);
-
-            }
-        }
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    send_reply(f, in, res, NULL, 0);
+    if (req->f->op.unlink)
+        req->f->op.unlink(req, nodeid, name);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_rmdir(struct fuse_ll *f, struct fuse_in_header *in, char *name)
+static void do_rmdir(fuse_req_t req, fuse_ino_t nodeid, char *name)
 {
-    int res;
-    char *path;
-
-    res = -ENOENT;
-    pthread_rwlock_wrlock(&f->tree_lock);
-    path = get_path_name(f, in->nodeid, name);
-    if (path != NULL) {
-        if (f->flags & FUSE_DEBUG) {
-            printf("RMDIR %s\n", path);
-            fflush(stdout);
-        }
-        res = -ENOSYS;
-        if (f->op.rmdir) {
-            res = f->op.rmdir(path);
-            if (res == 0)
-                remove_node(f, in->nodeid, name);
-        }
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    send_reply(f, in, res, NULL, 0);
+    if (req->f->op.rmdir)
+        req->f->op.rmdir(req, nodeid, name);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_symlink(struct fuse_ll *f, struct fuse_in_header *in, char *name,
+static void do_symlink(fuse_req_t req, fuse_ino_t nodeid, char *name,
                        char *link)
 {
-    int res;
-    int res2;
-    char *path;
-    struct fuse_entry_out outarg;
-
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path_name(f, in->nodeid, name);
-    if (path != NULL) {
-        if (f->flags & FUSE_DEBUG) {
-            printf("SYMLINK %s\n", path);
-            fflush(stdout);
-        }
-        res = -ENOSYS;
-        if (f->op.symlink && f->op.getattr) {
-            res = f->op.symlink(link, path);
-            if (res == 0)
-                res = lookup_path(f, in->nodeid, in->unique, name, path, &outarg);
-        }
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
-    if (res == 0 && res2 == -ENOENT)
-        cancel_lookup(f, outarg.nodeid, in->unique);
-
+    if (req->f->op.symlink)
+        req->f->op.symlink(req, link, nodeid, name);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_rename(struct fuse_ll *f, struct fuse_in_header *in,
-                      struct fuse_rename_in *inarg)
+static void do_rename(fuse_req_t req, fuse_ino_t nodeid,
+                      struct fuse_rename_in *arg)
 {
-    int res;
-    nodeid_t olddir = in->nodeid;
-    nodeid_t newdir = inarg->newdir;
-    char *oldname = PARAM(inarg);
+    char *oldname = PARAM(arg);
     char *newname = oldname + strlen(oldname) + 1;
-    char *oldpath;
-    char *newpath;
 
-    res = -ENOENT;
-    pthread_rwlock_wrlock(&f->tree_lock);
-    oldpath = get_path_name(f, olddir, oldname);
-    if (oldpath != NULL) {
-        newpath = get_path_name(f, newdir, newname);
-        if (newpath != NULL) {
-            if (f->flags & FUSE_DEBUG) {
-                printf("RENAME %s -> %s\n", oldpath, newpath);
-                fflush(stdout);
-            }
-            res = -ENOSYS;
-            if (f->op.rename) {
-                res = 0;
-                if (!(f->flags & FUSE_HARD_REMOVE) &&
-                    is_open(f, newdir, newname))
-                    res = hide_node(f, newpath, newdir, newname);
-                if (res == 0) {
-                    res = f->op.rename(oldpath, newpath);
-                    if (res == 0)
-                        res = rename_node(f, olddir, oldname, newdir, newname, 0);
-                }
-            }
-            free(newpath);
-        }
-        free(oldpath);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    send_reply(f, in, res, NULL, 0);
+    if (req->f->op.rename)
+        req->f->op.rename(req, nodeid, oldname, arg->newdir, newname);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_link(struct fuse_ll *f, struct fuse_in_header *in,
+static void do_link(fuse_req_t req, fuse_ino_t nodeid,
                     struct fuse_link_in *arg)
 {
-    int res;
-    int res2;
-    char *oldpath;
-    char *newpath;
-    char *name = PARAM(arg);
-    struct fuse_entry_out outarg;
-
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    oldpath = get_path(f, arg->oldnodeid);
-    if (oldpath != NULL) {
-        newpath =  get_path_name(f, in->nodeid, name);
-        if (newpath != NULL) {
-            if (f->flags & FUSE_DEBUG) {
-                printf("LINK %s\n", newpath);
-                fflush(stdout);
-            }
-            res = -ENOSYS;
-            if (f->op.link && f->op.getattr) {
-                res = f->op.link(oldpath, newpath);
-                if (res == 0)
-                    res = lookup_path(f, in->nodeid, in->unique, name,
-                                      newpath, &outarg);
-            }
-            free(newpath);
-        }
-        free(oldpath);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    res2 = send_reply(f, in, res, &outarg, sizeof(outarg));
-    if (res == 0 && res2 == -ENOENT)
-        cancel_lookup(f, outarg.nodeid, in->unique);
+    if (req->f->op.link)
+        req->f->op.link(req, arg->oldnodeid, nodeid, PARAM(arg));
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_open(struct fuse_ll *f, struct fuse_in_header *in,
+static void do_open(fuse_req_t req, fuse_ino_t nodeid,
                     struct fuse_open_in *arg)
 {
-    int res;
-    char *path;
-    struct fuse_open_out outarg;
     struct fuse_file_info fi;
 
-    memset(&outarg, 0, sizeof(outarg));
     memset(&fi, 0, sizeof(fi));
     fi.flags = arg->flags;
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path(f, in->nodeid);
-    if (path != NULL) {
-        res = -ENOSYS;
-        if (f->op.open) {
-            if (!f->compat)
-                res = f->op.open(path, &fi);
-            else
-                res = ((struct fuse_operations_compat2 *) &f->op)->open(path, fi.flags);
-        }
-    }
-    if (res == 0) {
-        int res2;
-        outarg.fh = fi.fh;
-        if (f->flags & FUSE_DEBUG) {
-            printf("OPEN[%lu] flags: 0x%x\n", fi.fh, arg->flags);
-            fflush(stdout);
-        }
-
-        pthread_mutex_lock(&f->lock);
-        res2 = send_reply(f, in, res, &outarg, SIZEOF_COMPAT(f, fuse_open_out));
-        if(res2 == -ENOENT) {
-            /* The open syscall was interrupted, so it must be cancelled */
-            if(f->op.release) {
-                if (!f->compat)
-                    f->op.release(path, &fi);
-                else
-                    ((struct fuse_operations_compat2 *) &f->op)->release(path, fi.flags);
-            }
-        } else {
-            struct node *node = get_node(f, in->nodeid);
-            node->open_count ++;
-        }
-        pthread_mutex_unlock(&f->lock);
-    } else
-        send_reply(f, in, res, NULL, 0);
 
-    if (path)
-        free(path);
-    pthread_rwlock_unlock(&f->tree_lock);
+    if (req->f->op.open)
+        req->f->op.open(req, nodeid, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_flush(struct fuse_ll *f, struct fuse_in_header *in,
-                     struct fuse_flush_in *arg)
+static void do_read(fuse_req_t req, fuse_ino_t nodeid,
+                    struct fuse_read_in *arg)
 {
-    char *path;
-    int res;
     struct fuse_file_info fi;
 
     memset(&fi, 0, sizeof(fi));
     fi.fh = arg->fh;
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path(f, in->nodeid);
-    if (path != NULL) {
-        if (f->flags & FUSE_DEBUG) {
-            printf("FLUSH[%lu]\n", (unsigned long) arg->fh);
-            fflush(stdout);
-        }
-        res = -ENOSYS;
-        if (f->op.flush)
-            res = f->op.flush(path, &fi);
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    send_reply(f, in, res, NULL, 0);
+
+    if (req->f->op.read)
+        req->f->op.read(req, nodeid, arg->size, arg->offset, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_release(struct fuse_ll *f, struct fuse_in_header *in,
-                       struct fuse_release_in *arg)
+static void do_write(fuse_req_t req, fuse_ino_t nodeid,
+                     struct fuse_write_in *arg)
 {
-    struct node *node;
-    char *path;
     struct fuse_file_info fi;
-    int unlink_hidden;
 
     memset(&fi, 0, sizeof(fi));
-    fi.flags = arg->flags;
     fi.fh = arg->fh;
+    fi.writepage = arg->write_flags & 1;
 
-    pthread_mutex_lock(&f->lock);
-    node = get_node(f, in->nodeid);
-    assert(node->open_count > 0);
-    --node->open_count;
-    unlink_hidden = (node->is_hidden && !node->open_count);
-    pthread_mutex_unlock(&f->lock);
-
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path(f, in->nodeid);
-    if (f->flags & FUSE_DEBUG) {
-        printf("RELEASE[%lu] flags: 0x%x\n", fi.fh, fi.flags);
-        fflush(stdout);
-    }
-    if (f->op.release) {
-        if (!f->compat)
-            f->op.release(path ? path : "-", &fi);
-        else if (path)
-            ((struct fuse_operations_compat2 *) &f->op)->release(path, fi.flags);
-    }
-
-    if(unlink_hidden && path)
-        f->op.unlink(path);
-
-    if (path)
-        free(path);
-    pthread_rwlock_unlock(&f->tree_lock);
-
-    send_reply(f, in, 0, NULL, 0);
+    if (req->f->op.write)
+        req->f->op.write(req, nodeid, PARAM(arg), arg->size, arg->offset, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_read(struct fuse_ll *f, struct fuse_in_header *in,
-                    struct fuse_read_in *arg)
+static void do_flush(fuse_req_t req, fuse_ino_t nodeid,
+                     struct fuse_flush_in *arg)
 {
-    int res;
-    char *path;
-    size_t size;
-    char *buf;
     struct fuse_file_info fi;
 
-    buf = (char *) malloc(arg->size);
-    if (buf == NULL) {
-        send_reply(f, in, -ENOMEM, NULL, 0);
-        return;
-    }
-
     memset(&fi, 0, sizeof(fi));
     fi.fh = arg->fh;
 
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path(f, in->nodeid);
-    if (path != NULL) {
-        if (f->flags & FUSE_DEBUG) {
-            printf("READ[%lu] %u bytes from %llu\n",
-                   (unsigned long) arg->fh, arg->size, arg->offset);
-            fflush(stdout);
-        }
-
-        res = -ENOSYS;
-        if (f->op.read)
-            res = f->op.read(path, buf, arg->size, arg->offset, &fi);
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-
-    size = 0;
-    if (res >= 0) {
-        size = res;
-        res = 0;
-        if (f->flags & FUSE_DEBUG) {
-            printf("   READ[%lu] %u bytes\n", (unsigned long) arg->fh,
-                   size);
-            fflush(stdout);
-        }
-    }
-
-    send_reply(f, in, res, buf, size);
-    free(buf);
+    if (req->f->op.flush)
+        req->f->op.flush(req, nodeid, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_write(struct fuse_ll *f, struct fuse_in_header *in,
-                     struct fuse_write_in *arg)
+static void do_release(fuse_req_t req, fuse_ino_t nodeid,
+                       struct fuse_release_in *arg)
 {
-    int res;
-    char *path;
-    struct fuse_write_out outarg;
     struct fuse_file_info fi;
 
     memset(&fi, 0, sizeof(fi));
+    fi.flags = arg->flags;
     fi.fh = arg->fh;
-    fi.writepage = arg->write_flags & 1;
 
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path(f, in->nodeid);
-    if (path != NULL) {
-        if (f->flags & FUSE_DEBUG) {
-            printf("WRITE%s[%lu] %u bytes to %llu\n",
-                   (arg->write_flags & 1) ? "PAGE" : "",
-                   (unsigned long) arg->fh, arg->size, arg->offset);
-            fflush(stdout);
-        }
+    if (req->f->op.release)
+        req->f->op.release(req, nodeid, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
 
-        res = -ENOSYS;
-        if (f->op.write)
-            res = f->op.write(path, PARAM(arg), arg->size, arg->offset, &fi);
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
+static void do_fsync(fuse_req_t req, fuse_ino_t nodeid,
+                     struct fuse_fsync_in *inarg)
+{
+    struct fuse_file_info fi;
 
-    memset(&outarg, 0, sizeof(outarg));
-    if (res >= 0) {
-        outarg.size = res;
-        res = 0;
-    }
+    memset(&fi, 0, sizeof(fi));
+    fi.fh = inarg->fh;
 
-    send_reply(f, in, res, &outarg, SIZEOF_COMPAT(f, fuse_write_out));
+    if (req->f->op.fsync)
+        req->f->op.fsync(req, nodeid, inarg->fsync_flags & 1, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static int default_statfs(struct statfs *buf)
+static void do_opendir(fuse_req_t req, fuse_ino_t nodeid,
+                       struct fuse_open_in *arg)
 {
-    buf->f_namelen = 255;
-    buf->f_bsize = 512;
-    return 0;
-}
+    struct fuse_file_info fi;
 
-static void convert_statfs_compat(struct fuse_statfs_compat1 *compatbuf,
-                                  struct statfs *statfs)
-{
-    statfs->f_bsize   = compatbuf->block_size;
-    statfs->f_blocks  = compatbuf->blocks;
-    statfs->f_bfree   = compatbuf->blocks_free;
-    statfs->f_bavail  = compatbuf->blocks_free;
-    statfs->f_files   = compatbuf->files;
-    statfs->f_ffree   = compatbuf->files_free;
-    statfs->f_namelen = compatbuf->namelen;
+    memset(&fi, 0, sizeof(fi));
+    fi.flags = arg->flags;
+
+    if (req->f->op.opendir)
+        req->f->op.opendir(req, nodeid, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void convert_statfs(struct statfs *statfs, struct fuse_kstatfs *kstatfs)
+static void do_readdir(fuse_req_t req, fuse_ino_t nodeid,
+                       struct fuse_read_in *arg)
 {
-    kstatfs->bsize     = statfs->f_bsize;
-    kstatfs->blocks    = statfs->f_blocks;
-    kstatfs->bfree     = statfs->f_bfree;
-    kstatfs->bavail    = statfs->f_bavail;
-    kstatfs->files     = statfs->f_files;
-    kstatfs->ffree     = statfs->f_ffree;
-    kstatfs->namelen   = statfs->f_namelen;
+    struct fuse_file_info fi;
+
+    memset(&fi, 0, sizeof(fi));
+    fi.fh = arg->fh;
+
+    if (req->f->op.readdir)
+        req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_statfs(struct fuse_ll *f, struct fuse_in_header *in)
+static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid,
+                          struct fuse_release_in *arg)
 {
-    int res;
-    struct fuse_statfs_out arg;
-    struct statfs buf;
-
-    memset(&buf, 0, sizeof(struct statfs));
-    if (f->op.statfs) {
-        if (!f->compat || f->compat > 11)
-            res = f->op.statfs("/", &buf);
-        else {
-            struct fuse_statfs_compat1 compatbuf;
-            memset(&compatbuf, 0, sizeof(struct fuse_statfs_compat1));
-            res = ((struct fuse_operations_compat1 *) &f->op)->statfs(&compatbuf);
-            if (res == 0)
-                convert_statfs_compat(&compatbuf, &buf);
-        }
-    }
-    else
-        res = default_statfs(&buf);
+    struct fuse_file_info fi;
 
-    if (res == 0)
-        convert_statfs(&buf, &arg.st);
+    memset(&fi, 0, sizeof(fi));
+    fi.flags = arg->flags;
+    fi.fh = arg->fh;
 
-    send_reply(f, in, res, &arg, sizeof(arg));
+    if (req->f->op.releasedir)
+        req->f->op.releasedir(req, nodeid, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
-static void do_fsync(struct fuse_ll *f, struct fuse_in_header *in,
-                     struct fuse_fsync_in *inarg)
+static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid,
+                        struct fuse_fsync_in *inarg)
 {
-    int res;
-    char *path;
     struct fuse_file_info fi;
 
     memset(&fi, 0, sizeof(fi));
     fi.fh = inarg->fh;
 
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path(f, in->nodeid);
-    if (path != NULL) {
-        if (f->flags & FUSE_DEBUG) {
-            printf("FSYNC[%lu]\n", (unsigned long) inarg->fh);
-            fflush(stdout);
-        }
-        res = -ENOSYS;
-        if (f->op.fsync)
-            res = f->op.fsync(path, inarg->fsync_flags & 1, &fi);
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    send_reply(f, in, res, NULL, 0);
+    if (req->f->op.fsyncdir)
+        req->f->op.fsyncdir(req, nodeid, inarg->fsync_flags & 1, &fi);
+    else
+        fuse_reply_err(req, ENOSYS);
+}
+
+static void do_statfs(fuse_req_t req, fuse_ino_t nodeid)
+{
+    if (req->f->op.statfs)
+        res = req->f->op.statfs(req, nodeid);
+    else
+        fuse_reply_err(req, ENOSYS);
 }
 
 static void do_setxattr(struct fuse_ll *f, struct fuse_in_header *in,
@@ -1102,267 +656,6 @@ static void do_init(struct fuse_ll *f, struct fuse_in_header *in,
     send_reply(f, in, 0, &outarg, sizeof(outarg));
 }
 
-static struct fuse_dirhandle *get_dirhandle(unsigned long fh)
-{
-    return (struct fuse_dirhandle *) fh;
-}
-
-static void do_opendir(struct fuse_ll *f, struct fuse_in_header *in,
-                       struct fuse_open_in *arg)
-{
-    int res;
-    struct fuse_open_out outarg;
-    struct fuse_dirhandle *dh;
-
-    dh = (struct fuse_dirhandle *) malloc(sizeof(struct fuse_dirhandle));
-    if (dh == NULL) {
-        send_reply(f, in, -ENOMEM, NULL, 0);
-        return;
-    }
-    memset(dh, 0, sizeof(struct fuse_dirhandle));
-    dh->fuse = f;
-    dh->contents = NULL;
-    dh->len = 0;
-    dh->filled = 0;
-    dh->nodeid = in->nodeid;
-    mutex_init(&dh->lock);
-
-    memset(&outarg, 0, sizeof(outarg));
-    outarg.fh = (unsigned long) dh;
-
-    if (f->op.opendir) {
-        struct fuse_file_info fi;
-        char *path;
-
-        memset(&fi, 0, sizeof(fi));
-        fi.flags = arg->flags;
-
-        res = -ENOENT;
-        pthread_rwlock_rdlock(&f->tree_lock);
-        path = get_path(f, in->nodeid);
-        if (path != NULL) {
-            res = f->op.opendir(path, &fi);
-            dh->fh = fi.fh;
-        }
-        if (res == 0) {
-            int res2;
-            pthread_mutex_lock(&f->lock);
-            res2 = send_reply(f, in, res, &outarg, SIZEOF_COMPAT(f, fuse_open_out));
-            if(res2 == -ENOENT) {
-                /* The opendir syscall was interrupted, so it must be
-                   cancelled */
-                if(f->op.releasedir)
-                    f->op.releasedir(path, &fi);
-                pthread_mutex_destroy(&dh->lock);
-                free(dh);
-            }
-            pthread_mutex_unlock(&f->lock);
-        } else {
-            send_reply(f, in, res, NULL, 0);
-            free(dh);
-        }
-        free(path);
-        pthread_rwlock_unlock(&f->tree_lock);
-    } else
-        send_reply(f, in, 0, &outarg, SIZEOF_COMPAT(f, fuse_open_out));
-}
-
-static int fill_dir_common(struct fuse_dirhandle *dh, const char *name,
-                           int type, ino_t ino, off_t off)
-{
-    unsigned namelen = strlen(name);
-    unsigned entlen;
-    unsigned entsize;
-    unsigned padlen;
-    unsigned newlen;
-    unsigned char *newptr;
-
-    if (!(dh->fuse->flags & FUSE_USE_INO)) {
-        ino = (ino_t) -1;
-        if (dh->fuse->flags & FUSE_READDIR_INO) {
-            struct node *node;
-            pthread_mutex_lock(&dh->fuse->lock);
-            node = lookup_node(dh->fuse, dh->nodeid, name);
-            if (node)
-                ino  = (ino_t) node->nodeid;
-            pthread_mutex_unlock(&dh->fuse->lock);
-        }
-    }
-
-    if (namelen > FUSE_NAME_MAX)
-        namelen = FUSE_NAME_MAX;
-    else if (!namelen) {
-        dh->error = -EIO;
-        return 1;
-    }
-
-    entlen = (dh->fuse->major == 5 ?
-              FUSE_NAME_OFFSET_COMPAT5 : FUSE_NAME_OFFSET) + namelen;
-    entsize = FUSE_DIRENT_ALIGN(entlen);
-    padlen = entsize - entlen;
-    newlen = dh->len + entsize;
-    if (off && dh->fuse->major != 5) {
-        dh->filled = 0;
-        if (newlen > dh->needlen)
-            return 1;
-    }
-
-    newptr = realloc(dh->contents, newlen);
-    if (!newptr) {
-        dh->error = -ENOMEM;
-        return 1;
-    }
-    dh->contents = newptr;
-    if (dh->fuse->major == 5) {
-        struct fuse_dirent_compat5 *dirent;
-        dirent = (struct fuse_dirent_compat5 *) (dh->contents + dh->len);
-        dirent->ino = ino;
-        dirent->namelen = namelen;
-        dirent->type = type;
-        strncpy(dirent->name, name, namelen);
-    } else {
-        struct fuse_dirent *dirent;
-        dirent = (struct fuse_dirent *) (dh->contents + dh->len);
-        dirent->ino = ino;
-        dirent->off = off ? off : newlen;
-        dirent->namelen = namelen;
-        dirent->type = type;
-        strncpy(dirent->name, name, namelen);
-    }
-    if (padlen)
-        memset(dh->contents + dh->len + entlen, 0, padlen);
-    dh->len = newlen;
-    return 0;
-}
-
-static int fill_dir(void *buf, const char *name, const struct stat *stat,
-                    off_t off)
-{
-    int type = stat ? (stat->st_mode & 0170000) >> 12 : 0;
-    ino_t ino = stat ? stat->st_ino : (ino_t) -1;
-    return fill_dir_common(buf, name, type, ino, off);
-}
-
-static int fill_dir_old(struct fuse_dirhandle *dh, const char *name, int type,
-                        ino_t ino)
-{
-    fill_dir_common(dh, name, type, ino, 0);
-    return dh->error;
-}
-
-static int readdir_fill(struct fuse_ll *f, struct fuse_in_header *in,
-                        struct fuse_read_in *arg, struct fuse_dirhandle *dh)
-{
-    int err = -ENOENT;
-    char *path;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path(f, in->nodeid);
-    if (path != NULL) {
-        struct fuse_file_info fi;
-
-        memset(&fi, 0, sizeof(fi));
-        fi.fh = dh->fh;
-
-        dh->len = 0;
-        dh->error = 0;
-        dh->needlen = arg->size;
-        dh->filled = 1;
-        err = -ENOSYS;
-        if (f->op.readdir) {
-            off_t offset = f->major == 5 ? 0 : arg->offset;
-            err = f->op.readdir(path, dh, fill_dir, offset, &fi);
-        } else if (f->op.getdir)
-            err = f->op.getdir(path, dh, fill_dir_old);
-        if (!err)
-            err = dh->error;
-        if (err)
-            dh->filled = 0;
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    return err;
-}
-
-static void do_readdir(struct fuse_ll *f, struct fuse_in_header *in,
-                       struct fuse_read_in *arg)
-{
-    int err = 0;
-    struct fuse_dirhandle *dh = get_dirhandle(arg->fh);
-    size_t size = 0;
-    unsigned char *buf = NULL;
-
-    pthread_mutex_lock(&dh->lock);
-    if (!dh->filled) {
-        err = readdir_fill(f, in, arg, dh);
-        if (err)
-            goto out;
-    }
-    if (dh->filled) {
-        if (arg->offset < dh->len) {
-            size = arg->size;
-            if (arg->offset + size > dh->len)
-                size = dh->len - arg->offset;
-            buf = dh->contents + arg->offset;
-        }
-    } else {
-        size = dh->len;
-        buf = dh->contents;
-    }
-
- out:
-    send_reply(f, in, err, buf, size);
-    pthread_mutex_unlock(&dh->lock);
-}
-
-static void do_releasedir(struct fuse_ll *f, struct fuse_in_header *in,
-                          struct fuse_release_in *arg)
-{
-    struct fuse_dirhandle *dh = get_dirhandle(arg->fh);
-    if (f->op.releasedir) {
-        char *path;
-        struct fuse_file_info fi;
-
-        memset(&fi, 0, sizeof(fi));
-        fi.fh = dh->fh;
-
-        pthread_rwlock_rdlock(&f->tree_lock);
-        path = get_path(f, in->nodeid);
-        f->op.releasedir(path ? path : "-", &fi);
-        free(path);
-        pthread_rwlock_unlock(&f->tree_lock);
-    }
-    pthread_mutex_lock(&dh->lock);
-    pthread_mutex_unlock(&dh->lock);
-    pthread_mutex_destroy(&dh->lock);
-    free(dh->contents);
-    free(dh);
-    send_reply(f, in, 0, NULL, 0);
-}
-
-static void do_fsyncdir(struct fuse_ll *f, struct fuse_in_header *in,
-                        struct fuse_fsync_in *inarg)
-{
-    int res;
-    char *path;
-    struct fuse_dirhandle *dh = get_dirhandle(inarg->fh);
-    struct fuse_file_info fi;
-
-    memset(&fi, 0, sizeof(fi));
-    fi.fh = dh->fh;
-
-    res = -ENOENT;
-    pthread_rwlock_rdlock(&f->tree_lock);
-    path = get_path(f, in->nodeid);
-    if (path != NULL) {
-        res = -ENOSYS;
-        if (f->op.fsyncdir)
-            res = f->op.fsyncdir(path, inarg->fsync_flags & 1, &fi);
-        free(path);
-    }
-    pthread_rwlock_unlock(&f->tree_lock);
-    send_reply(f, in, res, NULL, 0);
-}
-
 static void free_cmd(struct fuse_cmd *cmd)
 {
     free(cmd->buf);
@@ -1407,9 +700,12 @@ void fuse_process_cmd(struct fuse_ll *f, struct fuse_cmd *cmd)
 
     switch (in->opcode) {
     case FUSE_LOOKUP:
-        do_lookup(f, in, (char *) inarg);
+        do_lookup(f, req, nodeid, (char *) inarg);
         break;
 
+        do_forget(f, in, (struct fuse_forget_in *) inarg);
+        break;
+    }
     case FUSE_GETATTR:
         do_getattr(f, in);
         break;
@@ -1573,12 +869,6 @@ struct fuse_cmd *fuse_read_cmd(struct fuse_ll *f)
     }
     cmd->buflen = res;
 
-    /* Forget is special, it can be done without messing with threads. */
-    if (in->opcode == FUSE_FORGET) {
-        do_forget(f, in, (struct fuse_forget_in *) inarg);
-        free_cmd(cmd);
-        return NULL;
-    }
 
     return cmd;
 }
index 819a2b9c189751072a467692ac80e4cd25a3820b..48646847dcfc3772a96bb11f1df0544806181975 100644 (file)
@@ -94,15 +94,7 @@ static void *do_work(void *data)
 
 static int start_thread(struct fuse_worker *w, pthread_t *thread_id)
 {
-    sigset_t oldset;
-    sigset_t newset;
-    int res;
-
-    /* Disallow signal reception in worker threads */
-    sigfillset(&newset);
-    pthread_sigmask(SIG_SETMASK, &newset, &oldset);
-    res = pthread_create(thread_id, NULL, do_work, w);
-    pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+    int res = pthread_create(thread_id, NULL, do_work, w);
     if (res != 0) {
         fprintf(stderr, "fuse: error creating thread: %s\n", strerror(res));
         return -1;