summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2009-06-18 11:11:54 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2009-06-18 11:11:54 +0000
commitae9bfde712697205ac8809edc431cb7c0bdd484f (patch)
tree6f05932e39f7b1bfb44452bb09aecaa2826e4f0b
parentbc53eddb2f76be3e134aa5ed1814254aa289f898 (diff)
downloadfuse-ae9bfde712697205ac8809edc431cb7c0bdd484f.tar.gz
CUSE patches from Tejun Heo
-rw-r--r--ChangeLog31
-rw-r--r--example/Makefile.am2
-rw-r--r--example/fioc.h19
-rw-r--r--example/fioclient.c98
-rw-r--r--include/Makefile.am3
-rw-r--r--include/fuse_kernel.h31
-rw-r--r--include/fuse_lowlevel.h27
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/fuse.c28
-rw-r--r--lib/fuse_i.h69
-rw-r--r--lib/fuse_lowlevel.c136
-rw-r--r--lib/fuse_session.c12
-rw-r--r--lib/fuse_versionscript5
-rw-r--r--lib/helper.c16
14 files changed, 343 insertions, 135 deletions
diff --git a/ChangeLog b/ChangeLog
index 66f388f..f927d9b 100644
--- 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
diff --git a/example/Makefile.am b/example/Makefile.am
index 1aa5774..718b30a 100644
--- a/example/Makefile.am
+++ b/example/Makefile.am
@@ -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@
diff --git a/example/fioc.h b/example/fioc.h
index c1d9cdf..ec1a39d 100644
--- a/example/fioc.h
+++ b/example/fioc.h
@@ -12,6 +12,21 @@
#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 */
};
diff --git a/example/fioclient.c b/example/fioclient.c
index 3ab63b2..c056186 100644
--- a/example/fioclient.c
+++ b/example/fioclient.c
@@ -20,19 +20,56 @@
#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;
}
diff --git a/include/Makefile.am b/include/Makefile.am
index be2c592..663e164 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -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
diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h
index df558e3..541364f 100644
--- a/include/fuse_kernel.h
+++ b/include/fuse_kernel.h
@@ -150,6 +150,13 @@ struct fuse_file_lock {
#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
*/
#define FUSE_RELEASE_FLUSH (1 << 0)
@@ -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;
};
diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h
index 54cec8c..5ab2422 100644
--- a/include/fuse_lowlevel.h
+++ b/include/fuse_lowlevel.h
@@ -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
@@ -1116,6 +1117,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
*
* @param req request handle
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 0694980..7fce149 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -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) \
diff --git a/lib/fuse.c b/lib/fuse.c
index 8c27cd3..f7e78a8 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -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,
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index ec6e5d6..9bc1d70 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -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);
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 63a0668..e3b5d5d 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -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"
@@ -25,45 +24,6 @@
#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);
}
diff --git a/lib/fuse_session.c b/lib/fuse_session.c
index 5efedd9..7df4795 100644
--- a/lib/fuse_session.c
+++ b/lib/fuse_session.c
@@ -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"
@@ -17,16 +17,6 @@
#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;
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index f2608a8..4cd09aa 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -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;
diff --git a/lib/helper.c b/lib/helper.c
index d1cd075..3d0db4a 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -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;