aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/fuse.c22
-rw-r--r--lib/fuse_i.h3
-rw-r--r--lib/fuse_mt.c57
-rw-r--r--lib/helper.c5
4 files changed, 60 insertions, 27 deletions
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,