CUSE patches from Tejun Heo
authorMiklos Szeredi <miklos@szeredi.hu>
Thu, 18 Jun 2009 11:11:54 +0000 (11:11 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Thu, 18 Jun 2009 11:11:54 +0000 (11:11 +0000)
14 files changed:
ChangeLog
example/Makefile.am
example/fioc.h
example/fioclient.c
include/Makefile.am
include/fuse_kernel.h
include/fuse_lowlevel.h
lib/Makefile.am
lib/fuse.c
lib/fuse_i.h
lib/fuse_lowlevel.c
lib/fuse_session.c
lib/fuse_versionscript
lib/helper.c

index 66f388f980e09255e4531b6833722cf77c4a1e12..f927d9b09a4a5c2a4d271deb24906e9453686946 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,34 @@
+2009-06-18  Miklos Szeredi <miklos@szeredi.hu>
+
+       * CUSE patches from Tejun Heo:
+
+       * Unrestricted ioctl support left some debris.  Clean them up:
+         o No reason to pass around pointer to flags.  Pass flags directly.
+         o Clean up comment and prototype parameter names.
+         o fuse_lib_ioctl() didn't reply when get_path() failed.  Fix it.
+         o Remove unused variables {in|out}_iov from fuse_lib_ioctl().
+
+       * Add fuse_reply_ioctl_iov()
+
+       * Move fuse_session, fuse_req and fuse_ll definitions to fuse_i.h
+       and make send_reply_iov() and fuse_setup_common() global (also in
+       fuse_i.h).  These will be used by CUSE support.
+
+       * Restructure fuse_ll_process()
+
+       * Implement libfuse side of CUSE support.  CUSE uses subset of FUSE
+       operations as dir operations don't make sense for CUSE where one
+       instance implements single character device.
+
+       CUSE support comes with its own cuse_lowevel_ops and related
+       initialization and helper functions.  Except for initialization, it
+       usage is basically identical to FUSE.
+
+       This patch also adds example/cusexmp.c which can create a character
+       device with name and device number specified on command line.  The
+       created device itself is pretty boring.  It's a bit bucket supporting
+       read, write and access via ioctl.
+
 2009-06-16  Miklos Szeredi <miklos@szeredi.hu>
 
        * Add missing fuse_reply_bmap to versionscript.  Debian
index 1aa5774319f59021db725426aa34c7542772ea4e..718b30abdde2164e0f129842f2c5b43ee908c5c8 100644 (file)
@@ -3,7 +3,7 @@
 AM_CPPFLAGS = -I$(top_srcdir)/include -D_FILE_OFFSET_BITS=64 -D_REENTRANT
 noinst_HEADERS = fioc.h
 noinst_PROGRAMS = fusexmp fusexmp_fh null hello hello_ll fioc fioclient \
-                 fsel fselclient
+                 fsel fselclient cusexmp
 
 LDADD = ../lib/libfuse.la @libfuse_libs@
 fusexmp_fh_LDADD = ../lib/libfuse.la ../lib/libulockmgr.la @libfuse_libs@
index c1d9cdf2081ad3fcd56347201260b1919834bb1c..ec1a39dcc47a7c35841e426a327a623d0e8910b0 100644 (file)
 #include <sys/ioctl.h>
 
 enum {
-       FIOC_GET_SIZE = _IOR('E', 0, size_t),
-       FIOC_SET_SIZE = _IOW('E', 1, size_t),
+       FIOC_GET_SIZE   = _IOR('E', 0, size_t),
+       FIOC_SET_SIZE   = _IOW('E', 1, size_t),
+
+       /*
+        * The following two ioctls don't follow usual encoding rules
+        * and transfer variable amount of data.
+        */
+       FIOC_READ       = _IO('E', 2),
+       FIOC_WRITE      = _IO('E', 3),
+};
+
+struct fioc_rw_arg {
+       off_t           offset;
+       void            *buf;
+       size_t          size;
+       size_t          prev_size;      /* out param for previous total size */
+       size_t          new_size;       /* out param for new total size */
 };
index 3ab63b21e945314ac99da6e9a41d86509441e435..c056186f704494c7c3d94bb1277aeb615d199795 100644 (file)
 #include "fioc.h"
 
 const char *usage =
-"Usage: fioclient FIOC_FILE [SIZE]\n"
+"Usage: fioclient FIOC_FILE COMMAND\n"
 "\n"
-"       get size if SIZE is omitted, set size otherwise\n"
+"COMMANDS\n"
+"  s [SIZE]     : get size if SIZE is omitted, set size otherwise\n"
+"  r SIZE [OFF] : read SIZE bytes @ OFF (dfl 0) and output to stdout\n"
+"  w SIZE [OFF] : write SIZE bytes @ OFF (dfl 0) from stdin\n"
 "\n";
 
+static int do_rw(int fd, int is_read, size_t size, off_t offset,
+                size_t *prev_size, size_t *new_size)
+{
+       struct fioc_rw_arg arg = { .offset = offset };
+       ssize_t ret;
+
+       arg.buf = calloc(1, size);
+       if (!arg.buf) {
+               fprintf(stderr, "failed to allocated %zu bytes\n", size);
+               return -1;
+       }
+
+       if (is_read) {
+               arg.size = size;
+               ret = ioctl(fd, FIOC_READ, &arg);
+               if (ret >= 0)
+                       fwrite(arg.buf, 1, ret, stdout);
+       } else {
+               arg.size = fread(arg.buf, 1, size, stdin);
+               fprintf(stderr, "Writing %zu bytes\n", arg.size);
+               ret = ioctl(fd, FIOC_WRITE, &arg);
+       }
+
+       if (ret >= 0) {
+               *prev_size = arg.prev_size;
+               *new_size = arg.new_size;
+       } else
+               perror("ioctl");
+
+       free(arg.buf);
+       return ret;
+}
+
 int main(int argc, char **argv)
 {
-       size_t size;
-       int fd;
+       size_t param[2] = { };
+       size_t size, prev_size = 0, new_size = 0;
+       char cmd;
+       int fd, i, rc;
 
-       if (argc < 2) {
+       if (argc < 3)
                goto usage;
-       }
 
        fd = open(argv[1], O_RDWR);
        if (fd < 0) {
@@ -40,27 +77,46 @@ int main(int argc, char **argv)
                return 1;
        }
 
-       if (argc == 2) {
-               if (ioctl(fd, FIOC_GET_SIZE, &size)) {
-                       perror("ioctl");
-                       return 1;
-               }
-               printf("%zu\n", size);
-       } else {
-               char *endp;
+       cmd = tolower(argv[2][0]);
+       argc -= 3;
+       argv += 3;
 
-               size = strtoul(argv[2], &endp, 0);
-               if (endp == argv[2] || *endp != '\0')
+       for (i = 0; i < argc; i++) {
+               char *endp;
+               param[i] = strtoul(argv[i], &endp, 0);
+               if (endp == argv[i] || *endp != '\0')
                        goto usage;
+       }
 
-               if (ioctl(fd, FIOC_SET_SIZE, &size)) {
-                       perror("ioctl");
-                       return 1;
+       switch (cmd) {
+       case 's':
+               if (!argc) {
+                       if (ioctl(fd, FIOC_GET_SIZE, &size)) {
+                               perror("ioctl");
+                               return 1;
+                       }
+                       printf("%zu\n", size);
+               } else {
+                       size = param[0];
+                       if (ioctl(fd, FIOC_SET_SIZE, &size)) {
+                               perror("ioctl");
+                               return 1;
+                       }
                }
+               return 0;
+
+       case 'r':
+       case 'w':
+               rc = do_rw(fd, cmd == 'r', param[0], param[1],
+                          &prev_size, &new_size);
+               if (rc < 0)
+                       return 1;
+               fprintf(stderr, "transferred %d bytes (%zu -> %zu)\n",
+                       rc, prev_size, new_size);
+               return 0;
        }
-       return 0;
 
-usage:
+ usage:
        fprintf(stderr, usage);
        return 1;
 }
index be2c5929f7643ff86b578d1d53fc371c6856ae89..663e164cc9e7df77978d00837ef73953b17bb497 100644 (file)
@@ -9,7 +9,8 @@ fuseinclude_HEADERS = \
        fuse_common_compat.h    \
        fuse_lowlevel.h         \
        fuse_lowlevel_compat.h  \
-       fuse_opt.h
+       fuse_opt.h              \
+       cuse_lowlevel.h
 
 include_HEADERS = old/fuse.h ulockmgr.h
 
index df558e394ff5ac6c3b4b02c9b7932a3b6417ea83..541364fcccc77cd9c56c6c6b83000481bc32037a 100644 (file)
@@ -149,6 +149,13 @@ struct fuse_file_lock {
 #define FUSE_EXPORT_SUPPORT    (1 << 4)
 #define FUSE_BIG_WRITES                (1 << 5)
 
+/**
+ * CUSE INIT request/reply flags
+ *
+ * CUSE_UNRESTRICTED_IOCTL:  use unrestricted ioctl
+ */
+#define CUSE_UNRESTRICTED_IOCTL        (1 << 0)
+
 /**
  * Release flags
  */
@@ -239,6 +246,9 @@ enum fuse_opcode {
        FUSE_DESTROY       = 38,
        FUSE_IOCTL         = 39,
        FUSE_POLL          = 40,
+
+       /* CUSE specific operations */
+       CUSE_INIT          = 4096,
 };
 
 enum fuse_notify_code {
@@ -430,6 +440,27 @@ struct fuse_init_out {
        __u32   max_write;
 };
 
+#define CUSE_INIT_INFO_MAX 4096
+
+struct cuse_init_in {
+       __u32   major;
+       __u32   minor;
+       __u32   unused;
+       __u32   flags;
+};
+
+struct cuse_init_out {
+       __u32   major;
+       __u32   minor;
+       __u32   unused;
+       __u32   flags;
+       __u32   max_read;
+       __u32   max_write;
+       __u32   dev_major;              /* chardev major */
+       __u32   dev_minor;              /* chardev minor */
+       __u32   spare[10];
+};
+
 struct fuse_interrupt_in {
        __u64   unique;
 };
index 54cec8c85d7254b8c5dc39e8701f47fc82aecaba..5ab242290958c275d388dc14c810b7e7f4bf7198 100644 (file)
@@ -815,7 +815,7 @@ struct fuse_lowlevel_ops {
         *
         * Note: For unrestricted ioctls (not allowed for FUSE
         * servers), data in and out areas can be discovered by giving
-        * iovs and setting FUSE_IOCTL_RETRY in *flagsp.  For
+        * iovs and setting FUSE_IOCTL_RETRY in @flags.  For
         * restricted ioctls, kernel prepares in/out data area
         * according to the information encoded in cmd.
         *
@@ -824,6 +824,7 @@ struct fuse_lowlevel_ops {
         * Valid replies:
         *   fuse_reply_ioctl_retry
         *   fuse_reply_ioctl
+        *   fuse_reply_ioctl_iov
         *   fuse_reply_err
         *
         * @param req request handle
@@ -831,14 +832,14 @@ struct fuse_lowlevel_ops {
         * @param cmd ioctl command
         * @param arg ioctl argument
         * @param fi file information
-        * @param flagsp io/out parameter for FUSE_IOCTL_* flags
+        * @param flags for FUSE_IOCTL_* flags
         * @param in_buf data fetched from the caller
-        * @param in_size number of fetched bytes
-        * @param out_size maximum size of output data
+        * @param in_bufsz number of fetched bytes
+        * @param out_bufsz maximum size of output data
         */
        void (*ioctl) (fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
-                      struct fuse_file_info *fi, unsigned *flagsp,
-                      const void *in_buf, size_t in_bufsz, size_t out_bufszp);
+                      struct fuse_file_info *fi, unsigned flags,
+                      const void *in_buf, size_t in_bufsz, size_t out_bufsz);
 
        /**
         * Poll for IO readiness
@@ -1115,6 +1116,20 @@ int fuse_reply_ioctl_retry(fuse_req_t req,
  */
 int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size);
 
+/**
+ * Reply to finish ioctl with iov buffer
+ *
+ * Possible requests:
+ *   ioctl
+ *
+ * @param req request handle
+ * @param result result to be passed to the caller
+ * @param iov the vector containing the data
+ * @param count the size of vector
+ */
+int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov,
+                        int count);
+
 /**
  * Reply with poll result event mask
  *
index 06949804bed32067781739522ef11b35b241c27e..7fce149ef91c6ec9fd7d8687497a2bb0ec5ced64 100644 (file)
@@ -29,6 +29,7 @@ libfuse_la_SOURCES =          \
        fuse_opt.c              \
        fuse_session.c          \
        fuse_signals.c          \
+       cuse_lowlevel.c         \
        helper.c                \
        modules/subdir.c        \
        $(iconv_source)         \
index 8c27cd36beb338ecbb6c1ff76dc6f765717a5bcc..f7e78a8ea3d5a1b9bab3b8c66a1f6a25a81dc059 100644 (file)
@@ -3211,25 +3211,24 @@ static void fuse_lib_bmap(fuse_req_t req, fuse_ino_t ino, size_t blocksize,
 }
 
 static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
-                          struct fuse_file_info *fi, unsigned int *flagsp,
+                          struct fuse_file_info *fi, unsigned int flags,
                           const void *in_buf, size_t in_bufsz,
                           size_t out_bufsz)
 {
        struct fuse *f = req_fuse_prepare(req);
        struct fuse_intr_data d;
        char *path, *out_buf = NULL;
-       struct iovec *in_iov = NULL, *out_iov = NULL;
        int err;
 
-       if (*flagsp & FUSE_IOCTL_UNRESTRICTED) {
-               reply_err(req, -EPERM);
-               return;
-       }
+       err = -EPERM;
+       if (flags & FUSE_IOCTL_UNRESTRICTED)
+               goto err;
 
        if (out_bufsz) {
+               err = -ENOMEM;
                out_buf = malloc(out_bufsz);
                if (!out_buf)
-                       goto enomem;
+                       goto err;
        }
 
        assert(!in_bufsz || !out_bufsz || in_bufsz == out_bufsz);
@@ -3238,27 +3237,22 @@ static void fuse_lib_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
 
        err = get_path(f, ino, &path);
        if (err)
-               goto out;
+               goto err;
 
        fuse_prepare_interrupt(f, req, &d);
 
-       err = fuse_fs_ioctl(f->fs, path, cmd, arg, fi, *flagsp,
+       err = fuse_fs_ioctl(f->fs, path, cmd, arg, fi, flags,
                            out_buf ?: (void *)in_buf);
 
        fuse_finish_interrupt(f, req, &d);
        free_path(f, ino, path);
 
        fuse_reply_ioctl(req, err, out_buf, out_bufsz);
-
+       goto out;
+err:
+       reply_err(req, err);
 out:
        free(out_buf);
-       free(in_iov);
-       free(out_iov);
-       return;
-
-enomem:
-       reply_err(req, -ENOMEM);
-       goto out;
 }
 
 static void fuse_lib_poll(fuse_req_t req, fuse_ino_t ino,
index ec6e5d64ceeda440d677a694d93be4871ed21b19..9bc1d7065103a4fda65976fd1e5d4772c77b6996 100644 (file)
@@ -7,11 +7,58 @@
 */
 
 #include "fuse.h"
+#include "fuse_lowlevel.h"
 
-struct fuse_session;
 struct fuse_chan;
-struct fuse_lowlevel_ops;
-struct fuse_req;
+struct fuse_ll;
+
+struct fuse_session {
+       struct fuse_session_ops op;
+
+       void *data;
+
+       volatile int exited;
+
+       struct fuse_chan *ch;
+};
+
+struct fuse_req {
+       struct fuse_ll *f;
+       uint64_t unique;
+       int ctr;
+       pthread_mutex_t lock;
+       struct fuse_ctx ctx;
+       struct fuse_chan *ch;
+       int interrupted;
+       union {
+               struct {
+                       uint64_t unique;
+               } i;
+               struct {
+                       fuse_interrupt_func_t func;
+                       void *data;
+               } ni;
+       } u;
+       struct fuse_req *next;
+       struct fuse_req *prev;
+};
+
+struct fuse_ll {
+       int debug;
+       int allow_root;
+       int atomic_o_trunc;
+       int big_writes;
+       struct fuse_lowlevel_ops op;
+       int got_init;
+       struct cuse_data *cuse_data;
+       void *userdata;
+       uid_t owner;
+       struct fuse_conn_info conn;
+       struct fuse_req list;
+       struct fuse_req interrupts;
+       pthread_mutex_t lock;
+       int got_destroy;
+};
 
 struct fuse_cmd {
        char *buf;
@@ -34,3 +81,19 @@ struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
 void fuse_kern_unmount_compat22(const char *mountpoint);
 void fuse_kern_unmount(const char *mountpoint, int fd);
 int fuse_kern_mount(const char *mountpoint, struct fuse_args *args);
+
+int send_reply_iov(fuse_req_t req, int error, struct iovec *iov, int count);
+int send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov, int count);
+void free_req(fuse_req_t req);
+
+
+struct fuse *fuse_setup_common(int argc, char *argv[],
+                              const struct fuse_operations *op,
+                              size_t op_size,
+                              char **mountpoint,
+                              int *multithreaded,
+                              int *fd,
+                              void *user_data,
+                              int compat);
+
+void do_cuse_init(fuse_req_t req, fuse_ino_t nodeide, const void *inarg);
index 63a06683dd83bd82f6990c6f5fb60957fee6b05f..e3b5d5d35bf2f0f985b7b6372b75603a938859e9 100644 (file)
@@ -6,10 +6,9 @@
   See the file COPYING.LIB
 */
 
-#include "fuse_lowlevel.h"
+#include "fuse_i.h"
 #include "fuse_kernel.h"
 #include "fuse_opt.h"
-#include "fuse_i.h"
 #include "fuse_misc.h"
 #include "fuse_common_compat.h"
 #include "fuse_lowlevel_compat.h"
 #define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
 #define OFFSET_MAX 0x7fffffffffffffffLL
 
-struct fuse_ll;
-
-struct fuse_req {
-       struct fuse_ll *f;
-       uint64_t unique;
-       int ctr;
-       pthread_mutex_t lock;
-       struct fuse_ctx ctx;
-       struct fuse_chan *ch;
-       int interrupted;
-       union {
-               struct {
-                       uint64_t unique;
-               } i;
-               struct {
-                       fuse_interrupt_func_t func;
-                       void *data;
-               } ni;
-       } u;
-       struct fuse_req *next;
-       struct fuse_req *prev;
-};
-
-struct fuse_ll {
-       int debug;
-       int allow_root;
-       int atomic_o_trunc;
-       int big_writes;
-       struct fuse_lowlevel_ops op;
-       int got_init;
-       void *userdata;
-       uid_t owner;
-       struct fuse_conn_info conn;
-       struct fuse_req list;
-       struct fuse_req interrupts;
-       pthread_mutex_t lock;
-       int got_destroy;
-};
-
 struct fuse_pollhandle {
        uint64_t kh;
        struct fuse_chan *ch;
@@ -140,7 +100,7 @@ static void destroy_req(fuse_req_t req)
        free(req);
 }
 
-static void free_req(fuse_req_t req)
+void free_req(fuse_req_t req)
 {
        int ctr;
        struct fuse_ll *f = req->f;
@@ -155,11 +115,10 @@ static void free_req(fuse_req_t req)
                destroy_req(req);
 }
 
-static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
+int send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
                          int count)
 {
        struct fuse_out_header out;
-       int res;
 
        if (error <= -1000 || error > 0) {
                fprintf(stderr, "fuse: bad error value: %i\n",  error);
@@ -184,9 +143,16 @@ static int send_reply_iov(fuse_req_t req, int error, struct iovec *iov,
                                (unsigned long long) out.unique, out.len);
                }
        }
-       res = fuse_chan_send(req->ch, iov, count);
-       free_req(req);
 
+       return fuse_chan_send(req->ch, iov, count);
+}
+
+int send_reply_iov(fuse_req_t req, int error, struct iovec *iov, int count)
+{
+       int res;
+
+       res = send_reply_iov_nofree(req, error, iov, count);
+       free_req(req);
        return res;
 }
 
@@ -509,6 +475,30 @@ int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, size_t size)
        return send_reply_iov(req, 0, iov, count);
 }
 
+int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov,
+                        int count)
+{
+       struct iovec *padded_iov;
+       struct fuse_ioctl_out arg;
+       int res;
+
+       padded_iov = malloc((count + 2) * sizeof(struct iovec));
+       if (padded_iov == NULL)
+               return fuse_reply_err(req, -ENOMEM);
+
+       memset(&arg, 0, sizeof(arg));
+       arg.result = result;
+       padded_iov[1].iov_base = &arg;
+       padded_iov[1].iov_len = sizeof(arg);
+
+       memcpy(&padded_iov[2], iov, count * sizeof(struct iovec));
+
+       res = send_reply_iov(req, 0, padded_iov, count + 2);
+       free(padded_iov);
+
+       return res;
+}
+
 int fuse_reply_poll(fuse_req_t req, unsigned revents)
 {
        struct fuse_poll_out arg;
@@ -1095,7 +1085,7 @@ static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
 
        if (req->f->op.ioctl)
                req->f->op.ioctl(req, nodeid, arg->cmd,
-                                (void *)(uintptr_t)arg->arg, &fi, &flags,
+                                (void *)(uintptr_t)arg->arg, &fi, flags,
                                 in_buf, arg->in_size, arg->out_size);
        else
                fuse_reply_err(req, ENOSYS);
@@ -1356,6 +1346,7 @@ static struct {
        [FUSE_IOCTL]       = { do_ioctl,       "IOCTL"       },
        [FUSE_POLL]        = { do_poll,        "POLL"        },
        [FUSE_DESTROY]     = { do_destroy,     "DESTROY"     },
+       [CUSE_INIT]        = { do_cuse_init,   "CUSE_INIT"   },
 };
 
 #define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
@@ -1375,6 +1366,7 @@ static void fuse_ll_process(void *data, const char *buf, size_t len,
        struct fuse_in_header *in = (struct fuse_in_header *) buf;
        const void *inarg = buf + sizeof(struct fuse_in_header);
        struct fuse_req *req;
+       int err;
 
        if (f->debug)
                fprintf(stderr,
@@ -1399,28 +1391,41 @@ static void fuse_ll_process(void *data, const char *buf, size_t len,
        list_init_req(req);
        fuse_mutex_init(&req->lock);
 
-       if (!f->got_init && in->opcode != FUSE_INIT)
-               fuse_reply_err(req, EIO);
-       else if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
+       err = EIO;
+       if (!f->got_init) {
+               enum fuse_opcode expected;
+
+               expected = f->cuse_data ? CUSE_INIT : FUSE_INIT;
+               if (in->opcode != expected)
+                       goto reply_err;
+       } else if (in->opcode == FUSE_INIT || in->opcode == CUSE_INIT)
+               goto reply_err;
+
+       err = EACCES;
+       if (f->allow_root && in->uid != f->owner && in->uid != 0 &&
                 in->opcode != FUSE_INIT && in->opcode != FUSE_READ &&
                 in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
                 in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
-                in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR) {
-               fuse_reply_err(req, EACCES);
-       } else if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
-               fuse_reply_err(req, ENOSYS);
-       else {
-               if (in->opcode != FUSE_INTERRUPT) {
-                       struct fuse_req *intr;
-                       pthread_mutex_lock(&f->lock);
-                       intr = check_interrupt(f, req);
-                       list_add_req(req, &f->list);
-                       pthread_mutex_unlock(&f->lock);
-                       if (intr)
-                               fuse_reply_err(intr, EAGAIN);
-               }
-               fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
+                in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR)
+               goto reply_err;
+
+       err = ENOSYS;
+       if (in->opcode >= FUSE_MAXOP || !fuse_ll_ops[in->opcode].func)
+               goto reply_err;
+       if (in->opcode != FUSE_INTERRUPT) {
+               struct fuse_req *intr;
+               pthread_mutex_lock(&f->lock);
+               intr = check_interrupt(f, req);
+               list_add_req(req, &f->list);
+               pthread_mutex_unlock(&f->lock);
+               if (intr)
+                       fuse_reply_err(intr, EAGAIN);
        }
+       fuse_ll_ops[in->opcode].func(req, in->nodeid, inarg);
+       return;
+
+ reply_err:
+       fuse_reply_err(req, err);
 }
 
 enum {
@@ -1499,6 +1504,7 @@ static void fuse_ll_destroy(void *data)
        }
 
        pthread_mutex_destroy(&f->lock);
+       free(f->cuse_data);
        free(f);
 }
 
index 5efedd90c9395aa50f8c3f7e801f4dfe4b44eb57..7df47950e194fa0f21eb5b9f87984d3d696fde4d 100644 (file)
@@ -6,7 +6,7 @@
   See the file COPYING.LIB
 */
 
-#include "fuse_lowlevel.h"
+#include "fuse_i.h"
 #include "fuse_misc.h"
 #include "fuse_common_compat.h"
 #include "fuse_lowlevel_compat.h"
 #include <assert.h>
 #include <errno.h>
 
-struct fuse_session {
-       struct fuse_session_ops op;
-
-       void *data;
-
-       volatile int exited;
-
-       struct fuse_chan *ch;
-};
-
 struct fuse_chan {
        struct fuse_chan_ops op;
 
index f2608a8301bfb65834f51e5f707781f8826ced85..4cd09aa073dbf9735c8325a7d4c55280a40207c1 100644 (file)
@@ -160,6 +160,10 @@ FUSE_2.7.5 {
 
 FUSE_2.8 {
        global:
+               cuse_lowlevel_new;
+               cuse_lowlevel_main;
+               cuse_lowlevel_setup;
+               cuse_lowlevel_teardown;
                fuse_fs_ioctl;
                fuse_fs_poll;
                fuse_lowlevel_notify_poll;
@@ -167,6 +171,7 @@ FUSE_2.8 {
                fuse_opt_add_opt_escaped;
                fuse_pollhandle_destroy;
                fuse_reply_ioctl;
+               fuse_reply_ioctl_iov;
                fuse_reply_ioctl_retry;
                fuse_reply_poll;
 
index d1cd075d6d09ac6ccd2e5d55776ae8d9e48a9851..3d0db4a1f090fc2bcda621d45c2615ea10732e04 100644 (file)
@@ -235,14 +235,14 @@ void fuse_unmount(const char *mountpoint, struct fuse_chan *ch)
        fuse_unmount_common(mountpoint, ch);
 }
 
-static struct fuse *fuse_setup_common(int argc, char *argv[],
-                                     const struct fuse_operations *op,
-                                     size_t op_size,
-                                     char **mountpoint,
-                                     int *multithreaded,
-                                     int *fd,
-                                     void *user_data,
-                                     int compat)
+struct fuse *fuse_setup_common(int argc, char *argv[],
+                              const struct fuse_operations *op,
+                              size_t op_size,
+                              char **mountpoint,
+                              int *multithreaded,
+                              int *fd,
+                              void *user_data,
+                              int compat)
 {
        struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
        struct fuse_chan *ch;