Permalink
Browse files

Add idle_threads mount option.

  • Loading branch information...
joe0184 authored and Nikratio committed Aug 24, 2017
1 parent fc83143 commit f12d9686d4d673e59b8f561c49996820763220b1
Showing with 105 additions and 21 deletions.
  1. +7 −0 ChangeLog.rst
  2. +1 −1 configure.ac
  3. +7 −3 include/fuse.h
  4. +23 −1 include/fuse_common.h
  5. +8 −3 include/fuse_lowlevel.h
  6. +1 −1 lib/Makefile.am
  7. +6 −2 lib/cuse_lowlevel.c
  8. +14 −2 lib/fuse.c
  9. +17 −3 lib/fuse_loop_mt.c
  10. +6 −0 lib/fuse_versionscript
  11. +13 −3 lib/helper.c
  12. +1 −1 lib/meson.build
  13. +1 −1 meson.build
View
@@ -53,6 +53,13 @@ libfuse 3.1.1 (2017-08-06)
* Fixed a test failure when /tmp is on btrfs.
* The maximum number of idle worker threads used by `fuse_loop_mt()`
is now configurable.
* `fuse_loop_mt()` and `fuse_session_loop_mt()` now take a
`struct fuse_loop_config` parameter that supersedes the *clone_fd*
parameter.
* Incorporated several patches from the FreeBSD port. libfuse should
now compile under FreeBSD without the need for patches.
View
@@ -1,4 +1,4 @@
AC_INIT(fuse, 3.1.1)
AC_INIT(fuse, 3.2.0)
AC_PREREQ(2.59d)
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_TARGET
View
@@ -964,13 +964,17 @@ void fuse_exit(struct fuse *f);
* in the callback function of fuse_operations is also thread-safe.
*
* @param f the FUSE handle
* @param clone_fd whether to use separate device fds for each thread
* (may increase performance)
* @param config loop configuration
* @return see fuse_session_loop()
*
* See also: fuse_loop()
*/
int fuse_loop_mt(struct fuse *f, int clone_fd);
#if FUSE_USE_VERSION < 32
int fuse_loop_mt_31(struct fuse *f, int clone_fd);
#define fuse_loop_mt(f, clone_fd) fuse_loop_mt_31(f, clone_fd)
#else
int fuse_loop_mt(struct fuse *f, struct fuse_loop_config *config);
#endif
/**
* Get the current context
View
@@ -22,7 +22,7 @@
#define FUSE_MAJOR_VERSION 3
/** Minor version of FUSE library interface */
#define FUSE_MINOR_VERSION 1
#define FUSE_MINOR_VERSION 2
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
@@ -79,7 +79,29 @@ struct fuse_file_info {
uint32_t poll_events;
};
/**
* Configuration parameters passed to fuse_session_loop_mt() and
* fuse_loop_mt().
*/
struct fuse_loop_config {
/**
* whether to use separate device fds for each thread
* (may increase performance)
*/
int clone_fd;
/**
* The maximum number of available worker threads before they
* start to get deleted when they become idle. If not
* specified, the default is 10.
*
* Adjusting this has performance implications; a very small number
* of threads in the pool will cause a lot of thread creation and
* deletion overhead and performance may suffer. When set to 0, a new
* thread will be created to service every operation.
*/
unsigned int max_idle_threads;
};
/**************************************************************************
* Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want' *
View
@@ -1760,6 +1760,7 @@ struct fuse_cmdline_opts {
int show_version;
int show_help;
int clone_fd;
unsigned int max_idle_threads;
};
/**
@@ -1857,11 +1858,15 @@ int fuse_session_loop(struct fuse_session *se);
* fuse_session_loop().
*
* @param se the session
* @param clone_fd whether to use separate device fds for each thread
* (may increase performance)
* @param config session loop configuration
* @return see fuse_session_loop()
*/
int fuse_session_loop_mt(struct fuse_session *se, int clone_fd);
#if FUSE_USE_VERSION < 32
int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd);
#define fuse_session_loop_mt(se, clone_fd) fuse_session_loop_mt_31(se, clone_fd)
#else
int fuse_session_loop_mt(struct fuse_session *se, struct fuse_loop_config *config);
#endif
/**
* Flag a session as terminated.
View
@@ -1,7 +1,7 @@
## Process this file with automake to produce Makefile.in
AM_CPPFLAGS = -I$(top_srcdir)/include -DFUSERMOUNT_DIR=\"$(bindir)\" \
-D_REENTRANT -DFUSE_USE_VERSION=31
-D_REENTRANT -DFUSE_USE_VERSION=32
lib_LTLIBRARIES = libfuse3.la
View
@@ -349,8 +349,12 @@ int cuse_lowlevel_main(int argc, char *argv[], const struct cuse_info *ci,
if (se == NULL)
return 1;
if (multithreaded)
res = fuse_session_loop_mt(se, 0);
if (multithreaded) {
struct fuse_loop_config config;
config.clone_fd = 0;
config.max_idle_threads = 10;
res = fuse_session_loop_mt(se, &config);
}
else
res = fuse_session_loop(se);
View
@@ -4382,7 +4382,9 @@ int fuse_loop(struct fuse *f)
return fuse_session_loop(f->se);
}
int fuse_loop_mt(struct fuse *f, int clone_fd)
int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config);
FUSE_SYMVER(".symver fuse_loop_mt_32,fuse_loop_mt@@FUSE_3.2");
int fuse_loop_mt_32(struct fuse *f, struct fuse_loop_config *config)
{
if (f == NULL)
return -1;
@@ -4391,11 +4393,21 @@ int fuse_loop_mt(struct fuse *f, int clone_fd)
if (res)
return -1;
res = fuse_session_loop_mt(fuse_get_session(f), clone_fd);
res = fuse_session_loop_mt(fuse_get_session(f), config);
fuse_stop_cleanup_thread(f);
return res;
}
int fuse_loop_mt_31(struct fuse *f, int clone_fd);
FUSE_SYMVER(".symver fuse_loop_mt_31,fuse_loop_mt@FUSE_3.1");
int fuse_loop_mt_31(struct fuse *f, int clone_fd)
{
struct fuse_loop_config config;
config.clone_fd = clone_fd;
config.max_idle_threads = 10;
return fuse_loop_mt_32(f, &config);
}
void fuse_exit(struct fuse *f)
{
fuse_session_exit(f->se);
View
@@ -48,6 +48,7 @@ struct fuse_mt {
int exit;
int error;
int clone_fd;
int max_idle;
};
static struct fuse_chan *fuse_chan_new(int fd)
@@ -161,7 +162,7 @@ static void *fuse_do_work(void *data)
pthread_mutex_lock(&mt->lock);
if (!isforget)
mt->numavail++;
if (mt->numavail > 10) {
if (mt->numavail > mt->max_idle) {
if (mt->exit) {
pthread_mutex_unlock(&mt->lock);
return NULL;
@@ -300,18 +301,21 @@ static void fuse_join_worker(struct fuse_mt *mt, struct fuse_worker *w)
free(w);
}
int fuse_session_loop_mt(struct fuse_session *se, int clone_fd)
int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config);
FUSE_SYMVER(".symver fuse_session_loop_mt_32,fuse_session_loop_mt@@FUSE_3.2");
int fuse_session_loop_mt_32(struct fuse_session *se, struct fuse_loop_config *config)
{
int err;
struct fuse_mt mt;
struct fuse_worker *w;
memset(&mt, 0, sizeof(struct fuse_mt));
mt.se = se;
mt.clone_fd = clone_fd;
mt.clone_fd = config->clone_fd;
mt.error = 0;
mt.numworker = 0;
mt.numavail = 0;
mt.max_idle = config->max_idle_threads;
mt.main.thread_id = pthread_self();
mt.main.prev = mt.main.next = &mt.main;
sem_init(&mt.finish, 0, 0);
@@ -344,3 +348,13 @@ int fuse_session_loop_mt(struct fuse_session *se, int clone_fd)
fuse_session_reset(se);
return err;
}
int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd);
FUSE_SYMVER(".symver fuse_session_loop_mt_31,fuse_session_loop_mt@FUSE_3.1");
int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd)
{
struct fuse_loop_config config;
config.clone_fd = clone_fd;
config.max_idle_threads = 10;
return fuse_session_loop_mt_32(se, &config);
}
View
@@ -139,6 +139,12 @@ FUSE_3.1 {
fuse_invalidate_path;
} FUSE_3.0;
FUSE_3.2 {
global:
fuse_session_loop_mt_31;
fuse_loop_mt_31;
} FUSE_3.1;
# Local Variables:
# indent-tabs-mode: t
# End:
View
@@ -48,6 +48,7 @@ static const struct fuse_opt fuse_helper_opts[] = {
FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP),
#endif
FUSE_HELPER_OPT("clone_fd", clone_fd),
FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads),
FUSE_OPT_END
};
@@ -132,7 +133,9 @@ void fuse_cmdline_help(void)
" -f foreground operation\n"
" -s disable multi-threaded operation\n"
" -o clone_fd use separate fuse device fd for each thread\n"
" (may improve performance)\n");
" (may improve performance)\n"
" -o max_idle_threads the maximum number of idle worker threads\n"
" allowed (default: 10)\n");
}
static int fuse_helper_opt_proc(void *data, const char *arg, int key,
@@ -195,6 +198,9 @@ int fuse_parse_cmdline(struct fuse_args *args,
struct fuse_cmdline_opts *opts)
{
memset(opts, 0, sizeof(struct fuse_cmdline_opts));
opts->max_idle_threads = 10;
if (fuse_opt_parse(args, opts, fuse_helper_opts,
fuse_helper_opt_proc) == -1)
return -1;
@@ -326,8 +332,12 @@ int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
if (opts.singlethread)
res = fuse_loop(fuse);
else
res = fuse_loop_mt(fuse, opts.clone_fd);
else {
struct fuse_loop_config loop_config;
loop_config.clone_fd = opts.clone_fd;
loop_config.max_idle_threads = opts.max_idle_threads;
res = fuse_loop_mt(fuse, &loop_config);
}
if (res)
res = 1;
View
@@ -29,7 +29,7 @@ libfuse = library('fuse3', libfuse_sources, version: meson.project_version(),
soversion: '3', include_directories: include_dirs,
dependencies: deps, install: true,
link_depends: 'fuse_versionscript',
c_args: [ '-DFUSE_USE_VERSION=31',
c_args: [ '-DFUSE_USE_VERSION=32',
'-DFUSERMOUNT_DIR="{}"'.format(fusermount_path) ],
link_args: ['-Wl,--version-script,' + meson.current_source_dir()
+ '/fuse_versionscript' ])
View
@@ -1,4 +1,4 @@
project('libfuse3', 'c', version: '3.1.1',
project('libfuse3', 'c', version: '3.2.0',
meson_version: '>= 0.38',
default_options: [ 'buildtype=debugoptimized' ])

0 comments on commit f12d968

Please sign in to comment.