diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fuse_i.h | 7 | ||||
-rw-r--r-- | lib/fuse_loop_mt.c | 26 | ||||
-rw-r--r-- | lib/fuse_versionscript | 4 | ||||
-rw-r--r-- | lib/helper.c | 47 |
4 files changed, 78 insertions, 6 deletions
diff --git a/lib/fuse_i.h b/lib/fuse_i.h index 6930a20..42f0e5f 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -128,6 +128,13 @@ struct fuse_loop_config * The special value of -1 means that this parameter is disabled. */ int max_idle_threads; + + /** + * max number of threads taking and processing kernel requests + * + * As of now threads are created dynamically + */ + unsigned int max_threads; }; #endif diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c index 2f0470b..9ec1fb2 100644 --- a/lib/fuse_loop_mt.c +++ b/lib/fuse_loop_mt.c @@ -31,6 +31,7 @@ #define FUSE_LOOP_MT_V2_IDENTIFIER INT_MAX - 2 #define FUSE_LOOP_MT_DEF_CLONE_FD 0 +#define FUSE_LOOP_MT_DEF_MAX_THREADS 10 #define FUSE_LOOP_MT_DEF_IDLE_THREADS -1 /* thread destruction is disabled * by default */ @@ -57,6 +58,7 @@ struct fuse_mt { int error; int clone_fd; int max_idle; + int max_threads; }; static struct fuse_chan *fuse_chan_new(int fd) @@ -161,7 +163,7 @@ static void *fuse_do_work(void *data) if (!isforget) mt->numavail--; - if (mt->numavail == 0) + if (mt->numavail == 0 && mt->numworker < mt->max_threads) fuse_loop_start_thread(mt); pthread_mutex_unlock(&mt->lock); @@ -170,7 +172,14 @@ static void *fuse_do_work(void *data) pthread_mutex_lock(&mt->lock); if (!isforget) mt->numavail++; - if (mt->numavail > mt->max_idle) { + + /* creating and destroying threads is rather expensive - and there is + * not much gain from destroying existing threads. It is therefore + * discouraged to set max_idle to anything else than -1. If there + * is indeed a good reason to destruct threads it should be done + * delayed, a moving average might be useful for that. + */ + if (mt->max_idle != -1 && mt->numavail > mt->max_idle) { if (mt->exit) { pthread_mutex_unlock(&mt->lock); return NULL; @@ -202,7 +211,10 @@ int fuse_start_thread(pthread_t *thread_id, void *(*func)(void *), void *arg) pthread_attr_t attr; char *stack_size; - /* Override default stack size */ + /* Override default stack size + * XXX: This should ideally be a parameter option. It is rather + * well hidden here. + */ pthread_attr_init(&attr); stack_size = getenv(ENVNAME_THREAD_STACK); if (stack_size && pthread_attr_setstacksize(&attr, atoi(stack_size))) @@ -328,6 +340,7 @@ int err; mt.numworker = 0; mt.numavail = 0; mt.max_idle = config->max_idle_threads; + mt.max_threads = config->max_threads; mt.main.thread_id = pthread_self(); mt.main.prev = mt.main.next = &mt.main; sem_init(&mt.finish, 0, 0); @@ -400,6 +413,7 @@ struct fuse_loop_config *fuse_loop_cfg_create(void) config->version_id = FUSE_LOOP_MT_V2_IDENTIFIER; config->max_idle_threads = FUSE_LOOP_MT_DEF_IDLE_THREADS; + config->max_threads = FUSE_LOOP_MT_DEF_MAX_THREADS; config->clone_fd = FUSE_LOOP_MT_DEF_CLONE_FD; return config; @@ -432,6 +446,12 @@ void fuse_loop_cfg_set_idle_threads(struct fuse_loop_config *config, config->max_idle_threads = value; } +void fuse_loop_cfg_set_max_threads(struct fuse_loop_config *config, + unsigned int value) +{ + config->max_threads = value; +} + void fuse_loop_cfg_set_clone_fd(struct fuse_loop_config *config, unsigned int value) { diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index aff7e84..7e50e75 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -178,8 +178,12 @@ FUSE_3.12 { fuse_loop_cfg_create; fuse_loop_cfg_destroy; fuse_loop_cfg_set_idle_threads; + fuse_loop_cfg_set_max_threads; fuse_loop_cfg_set_clone_fd; fuse_loop_cfg_convert; + fuse_parse_cmdline; + fuse_parse_cmdline_30; + fuse_parse_cmdline_312; } FUSE_3.4; # Local Variables: diff --git a/lib/helper.c b/lib/helper.c index fc6a6ee..ea5f87d 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -50,6 +50,7 @@ static const struct fuse_opt fuse_helper_opts[] = { #endif FUSE_HELPER_OPT("clone_fd", clone_fd), FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads), + FUSE_HELPER_OPT("max_threads=%u", max_threads), FUSE_OPT_END }; @@ -136,6 +137,8 @@ void fuse_cmdline_help(void) " -o clone_fd use separate fuse device fd for each thread\n" " (may improve performance)\n" " -o max_idle_threads the maximum number of idle worker threads\n" + " allowed (default: -1)\n" + " -o max_threads the maximum number of worker threads\n" " allowed (default: 10)\n"); } @@ -199,12 +202,16 @@ static int add_default_subtype(const char *progname, struct fuse_args *args) return res; } -int fuse_parse_cmdline(struct fuse_args *args, - struct fuse_cmdline_opts *opts) +int fuse_parse_cmdline_312(struct fuse_args *args, + struct fuse_cmdline_opts *opts); +FUSE_SYMVER("fuse_parse_cmdline_312", "fuse_parse_cmdline@@FUSE_3.12") +int fuse_parse_cmdline_312(struct fuse_args *args, + struct fuse_cmdline_opts *opts) { memset(opts, 0, sizeof(struct fuse_cmdline_opts)); - opts->max_idle_threads = 10; + opts->max_idle_threads = -1; /* new default in fuse version 3.12 */ + opts->max_threads = 10; if (fuse_opt_parse(args, opts, fuse_helper_opts, fuse_helper_opt_proc) == -1) @@ -221,6 +228,40 @@ int fuse_parse_cmdline(struct fuse_args *args, return 0; } +/** + * struct fuse_cmdline_opts got extended in libfuse-3.12 + */ +int fuse_parse_cmdline_30(struct fuse_args *args, + struct fuse_cmdline_opts *opts); +FUSE_SYMVER("fuse_parse_cmdline_37", "fuse_parse_cmdline@FUSE_3.0") +int fuse_parse_cmdline_30(struct fuse_args *args, + struct fuse_cmdline_opts *out_opts) +{ + struct fuse_cmdline_opts opts; + + + int rc = fuse_parse_cmdline_312(args, &opts); + if (rc == 0) { + /* copy up to the size of the old pre 3.12 struct */ + memcpy(out_opts, &opts, + offsetof(struct fuse_cmdline_opts, max_idle_threads) + + sizeof(opts.max_idle_threads)); + } + + return rc; +} + +/** + * Compatibility ABI symbol for systems that do not support version symboling + */ +#if (defined(__UCLIBC__) || defined(__APPLE__)) +int fuse_parse_cmdline(struct fuse_args *args, + struct fuse_cmdline_opts *opts) +{ + return fuse_parse_cmdline_30(args, out_opts); +} +#endif + int fuse_daemonize(int foreground) { |