diff options
Diffstat (limited to 'lib/fuse_lowlevel.c')
-rw-r--r-- | lib/fuse_lowlevel.c | 97 |
1 files changed, 69 insertions, 28 deletions
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 495eb1d..b89ad93 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -6,7 +6,8 @@ See the file COPYING.LIB */ -#include "fuse_lowlevel.h" +#include <config.h> +#include "fuse_lowlevel_i.h" #include "fuse_kernel.h" #include <stdio.h> @@ -22,19 +23,6 @@ #define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg))) -struct fuse_ll { - unsigned int debug : 1; - unsigned int allow_root : 1; - int fd; - struct fuse_ll_operations op; - volatile int exited; - int got_init; - void *user_data; - int major; - int minor; - uid_t owner; -}; - struct fuse_cmd { char *buf; size_t buflen; @@ -43,11 +31,22 @@ struct fuse_cmd { struct fuse_req { struct fuse_ll *f; uint64_t unique; - uid_t uid; - gid_t gid; - pid_t pid; + struct fuse_ctx ctx; }; +#ifndef USE_UCLIBC +#define mutex_init(mut) pthread_mutex_init(mut, NULL) +#else +static void mutex_init(pthread_mutex_t *mut) +{ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP); + pthread_mutex_init(mut, &attr); + pthread_mutexattr_destroy(&attr); +} +#endif + static const char *opname(enum fuse_opcode opcode) { switch (opcode) { @@ -83,6 +82,20 @@ static const char *opname(enum fuse_opcode opcode) } } +static inline void fuse_dec_avail(struct fuse_ll *f) +{ + pthread_mutex_lock(&f->worker_lock); + f->numavail --; + pthread_mutex_unlock(&f->worker_lock); +} + +static inline void fuse_inc_avail(struct fuse_ll *f) +{ + pthread_mutex_lock(&f->worker_lock); + f->numavail ++; + pthread_mutex_unlock(&f->worker_lock); +} + static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr) { attr->ino = stbuf->st_ino; @@ -143,10 +156,15 @@ static int send_reply_raw(struct fuse_ll *f, const struct iovec iov[], fflush(stdout); } + /* This needs to be done before the reply, otherwise the scheduler + could play tricks with us, and only let the counter be + increased long after the operation is done */ + fuse_inc_avail(f); + res = writev(f->fd, iov, count); if (res == -1) { /* ENOENT means the operation was interrupted */ - if (!f->exited && errno != ENOENT) + if (!fuse_ll_exited(f) && errno != ENOENT) perror("fuse: writing device"); return -errno; } @@ -589,10 +607,10 @@ static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, fuse_reply_err(req, ENOSYS); } -static void do_statfs(fuse_req_t req, fuse_ino_t nodeid) +static void do_statfs(fuse_req_t req) { if (req->f->op.statfs) - req->f->op.statfs(req, nodeid); + req->f->op.statfs(req); else fuse_reply_err(req, ENOSYS); } @@ -647,7 +665,7 @@ static void do_init(struct fuse_ll *f, uint64_t unique, } f->got_init = 1; if (f->op.init) - f->user_data = f->op.init(); + f->userdata = f->op.init(f->userdata); f->major = FUSE_KERNEL_VERSION; f->minor = FUSE_KERNEL_MINOR_VERSION; @@ -664,6 +682,16 @@ static void do_init(struct fuse_ll *f, uint64_t unique, send_reply(f, unique, 0, &outarg, sizeof(outarg)); } +void *fuse_req_userdata(fuse_req_t req) +{ + return req->f->userdata; +} + +const struct fuse_ctx *fuse_req_ctx(fuse_req_t req) +{ + return &req->ctx; +} + static void free_cmd(struct fuse_cmd *cmd) { free(cmd->buf); @@ -676,6 +704,8 @@ void fuse_ll_process_cmd(struct fuse_ll *f, struct fuse_cmd *cmd) void *inarg = cmd->buf + sizeof(struct fuse_in_header); struct fuse_req *req; + fuse_dec_avail(f); + if (f->debug) { printf("unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %i\n", in->unique, opname(in->opcode), in->opcode, @@ -708,9 +738,9 @@ void fuse_ll_process_cmd(struct fuse_ll *f, struct fuse_cmd *cmd) req->f = f; req->unique = in->unique; - req->uid = in->uid; - req->gid = in->gid; - req->pid = in->pid; + req->ctx.uid = in->uid; + req->ctx.gid = in->gid; + req->ctx.pid = in->pid; switch (in->opcode) { case FUSE_LOOKUP: @@ -783,7 +813,7 @@ void fuse_ll_process_cmd(struct fuse_ll *f, struct fuse_cmd *cmd) break; case FUSE_STATFS: - do_statfs(req, in->nodeid); + do_statfs(req); break; case FUSE_FSYNC: @@ -830,6 +860,11 @@ void fuse_ll_process_cmd(struct fuse_ll *f, struct fuse_cmd *cmd) free_cmd(cmd); } +void fuse_ll_exit(struct fuse_ll *f) +{ + f->exited = 1; +} + int fuse_ll_exited(struct fuse_ll* f) { return f->exited; @@ -868,14 +903,14 @@ struct fuse_cmd *fuse_ll_read_cmd(struct fuse_ll *f) perror("fuse: reading device"); } - f->exited = 1; + fuse_ll_exit(f); return NULL; } if ((size_t) res < sizeof(struct fuse_in_header)) { free_cmd(cmd); /* Cannot happen */ fprintf(stderr, "short read on fuse device\n"); - f->exited = 1; + fuse_ll_exit(f); return NULL; } cmd->buflen = res; @@ -941,7 +976,7 @@ static int parse_ll_opts(struct fuse_ll *f, const char *opts) struct fuse_ll *fuse_ll_new(int fd, const char *opts, const struct fuse_ll_operations *op, - size_t op_size) + size_t op_size, void *userdata) { struct fuse_ll *f; @@ -963,6 +998,8 @@ struct fuse_ll *fuse_ll_new(int fd, const char *opts, memcpy(&f->op, op, op_size); f->exited = 0; f->owner = getuid(); + f->userdata = userdata; + mutex_init(&f->worker_lock); return f; @@ -974,6 +1011,10 @@ struct fuse_ll *fuse_ll_new(int fd, const char *opts, void fuse_ll_destroy(struct fuse_ll *f) { + if (f->op.destroy) + f->op.destroy(f->userdata); + + pthread_mutex_destroy(&f->worker_lock); free(f); } |