From: Miklos Szeredi Date: Wed, 22 Sep 2004 08:48:26 +0000 (+0000) Subject: fix X-Git-Tag: fuse_1_9~8 X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=d169f31d6926c5bdc7c66822b6a49c87ddf7f901;p=qemu-gpiodev%2Flibfuse.git fix --- diff --git a/ChangeLog b/ChangeLog index 891dfd9..c3fc2d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2004-09-22 Miklos Szeredi + + * A slight API change: fuse_get_context() doesn't need the "fuse" + pointer, but the returned context contains it instead. The + fuse_get() function is not needed anymore, so it's removed. + 2004-09-21 Miklos Szeredi * Fix deadlock in case of memory allocation failure. Patch by diff --git a/include/fuse.h b/include/fuse.h index 81ef0d4..22de11b 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -133,6 +133,7 @@ struct fuse_operations { /** Extra context that may be needed by some filesystems */ struct fuse_context { + struct fuse *fuse; uid_t uid; gid_t gid; }; @@ -162,15 +163,6 @@ extern "C" { */ void fuse_main(int argc, char *argv[], const struct fuse_operations *op); -/* - * Returns the fuse object created by fuse_main() - * - * This is useful when fuse_get_context() is used. - * - * @return the fuse object - */ -struct fuse *fuse_get(void); - /** * Invalidate cached data of a file. * @@ -266,7 +258,7 @@ int fuse_loop_mt(struct fuse *f); * @param f the FUSE handle * @return the context */ -struct fuse_context *fuse_get_context(struct fuse *f); +struct fuse_context *fuse_get_context(void); /** * Check whether a mount option should be passed to the kernel or the @@ -288,6 +280,7 @@ struct fuse_cmd *__fuse_read_cmd(struct fuse *f); void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd); int __fuse_loop_mt(struct fuse *f, fuse_processor_t proc, void *data); int __fuse_exited(struct fuse* f); +void __fuse_set_getcontext_func(struct fuse_context *(*func)(void)); #ifdef __cplusplus } diff --git a/lib/fuse.c b/lib/fuse.c index a4d547a..fae68a1 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -23,6 +23,8 @@ #define ENTRY_REVALIDATE_TIME 1 /* sec */ #define ATTR_REVALIDATE_TIME 1 /* sec */ +static struct fuse_context *(*fuse_getcontext)(void) = NULL; + static const char *opname(enum fuse_opcode opcode) { switch (opcode) { @@ -1428,7 +1430,7 @@ void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd) struct fuse_in_header *in = (struct fuse_in_header *) cmd->buf; void *inarg = cmd->buf + sizeof(struct fuse_in_header); size_t argsize; - struct fuse_context *ctx = fuse_get_context(f); + struct fuse_context *ctx = fuse_get_context(); dec_avail(f); @@ -1439,6 +1441,7 @@ void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd) fflush(stdout); } + ctx->fuse = f; ctx->uid = in->uid; ctx->gid = in->gid; @@ -1664,12 +1667,18 @@ void fuse_exit(struct fuse *f) f->exited = 1; } -struct fuse_context *fuse_get_context(struct fuse *f) +struct fuse_context *fuse_get_context() { - if (f->getcontext) - return f->getcontext(f); + static struct fuse_context context; + if (fuse_getcontext) + return fuse_getcontext(); else - return &f->context; + return &context; +} + +void __fuse_set_getcontext_func(struct fuse_context *(*func)(void)) +{ + fuse_getcontext = func; } static int check_version(struct fuse *f) @@ -1769,9 +1778,6 @@ struct fuse *fuse_new(int fd, const char *opts, const struct fuse_operations *op f->numworker = 0; f->numavail = 0; f->op = *op; - f->getcontext = NULL; - f->context.uid = 0; - f->context.gid = 0; f->exited = 0; root = (struct node *) calloc(1, sizeof(struct node)); diff --git a/lib/fuse_i.h b/lib/fuse_i.h index 3817062..c1aaa4c 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -51,9 +51,6 @@ struct fuse { pthread_mutex_t lock; int numworker; int numavail; - struct fuse_context *(*getcontext)(struct fuse *); - struct fuse_context context; - pthread_key_t context_key; volatile int exited; int majorver; int minorver; diff --git a/lib/fuse_mt.c b/lib/fuse_mt.c index 8bac5ff..345da33 100644 --- a/lib/fuse_mt.c +++ b/lib/fuse_mt.c @@ -25,6 +25,10 @@ struct fuse_worker { fuse_processor_t proc; }; +static pthread_key_t context_key; +static pthread_mutex_t context_lock = PTHREAD_MUTEX_INITIALIZER; +static int context_ref; + static int start_thread(struct fuse_worker *w, pthread_t *thread_id); static void *do_work(void *data) @@ -41,7 +45,7 @@ static void *do_work(void *data) pthread_mutex_unlock(&f->lock); return NULL; } - pthread_setspecific(f->context_key, ctx); + pthread_setspecific(context_key, ctx); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); @@ -94,7 +98,7 @@ static int start_thread(struct fuse_worker *w, pthread_t *thread_id) res = pthread_create(thread_id, NULL, do_work, w); pthread_sigmask(SIG_SETMASK, &oldset, NULL); if (res != 0) { - fprintf(stderr, "Error creating thread: %s\n", strerror(res)); + fprintf(stderr, "fuse: error creating thread: %s\n", strerror(res)); return -1; } @@ -102,9 +106,14 @@ static int start_thread(struct fuse_worker *w, pthread_t *thread_id) return 0; } -static struct fuse_context *mt_getcontext(struct fuse *f) +static struct fuse_context *mt_getcontext(void) { - return (struct fuse_context *) pthread_getspecific(f->context_key); + struct fuse_context *ctx = + (struct fuse_context *) pthread_getspecific(context_key); + if (ctx == NULL) + fprintf(stderr, "fuse: no thread specific data for this thread\n"); + + return ctx; } static void mt_freecontext(void *data) @@ -112,10 +121,38 @@ static void mt_freecontext(void *data) free(data); } +static int mt_create_context_key() +{ + int err = 0; + pthread_mutex_lock(&context_lock); + if (!context_ref) { + err = pthread_key_create(&context_key, mt_freecontext); + if (err) + fprintf(stderr, "fuse: failed to create thread specific key: %s\n", + strerror(err)); + else + __fuse_set_getcontext_func(mt_getcontext); + } + if (!err) + context_ref ++; + pthread_mutex_unlock(&context_lock); + return err; +} + +static void mt_delete_context_key() +{ + pthread_mutex_lock(&context_lock); + context_ref--; + if (!context_ref) { + __fuse_set_getcontext_func(NULL); + pthread_key_delete(context_key); + } + pthread_mutex_unlock(&context_lock); +} + int __fuse_loop_mt(struct fuse *f, fuse_processor_t proc, void *data) { struct fuse_worker *w; - int res; int i; w = malloc(sizeof(struct fuse_worker)); @@ -128,20 +165,18 @@ int __fuse_loop_mt(struct fuse *f, fuse_processor_t proc, void *data) w->data = data; w->proc = proc; - f->numworker = 1; - res = pthread_key_create(&f->context_key, mt_freecontext); - if (res != 0) { - fprintf(stderr, "Failed to create thread specific key\n"); + if (mt_create_context_key() != 0) { + free(w); return -1; } - f->getcontext = mt_getcontext; + f->numworker = 1; do_work(w); pthread_mutex_lock(&f->lock); for (i = 1; i < f->numworker; i++) pthread_cancel(w->threads[i]); pthread_mutex_unlock(&f->lock); - pthread_key_delete(f->context_key); + mt_delete_context_key(); free(w); return 0; } diff --git a/lib/helper.c b/lib/helper.c index b9e8150..6031c5f 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -17,11 +17,6 @@ static struct fuse *fuse; -struct fuse *fuse_get(void) -{ - return fuse; -} - static void usage(char *progname) { fprintf(stderr,