diff options
author | Ralph Boehme <slow@samba.org> | 2018-03-13 16:59:32 +0100 |
---|---|---|
committer | Ralph Boehme <slow@samba.org> | 2018-07-24 17:38:27 +0200 |
commit | 65e4742d168454df6507d9e74993749063435dd6 (patch) | |
tree | 2b920630ffeb36972db502fe4da4c6bd06e07977 | |
parent | 7cb27238fe4e6dfc45cf3128ccd4a392aaf4e877 (diff) | |
download | samba-65e4742d168454df6507d9e74993749063435dd6.tar.gz |
pthreadpool: call unshare(CLONE_FS) if available
This paves the way for pthreadpool jobs that are path based.
Callers can use pthreadpool_per_thread_cwd() to check if
the current pool supports it.
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Ralph Boehme <slow@samba.org>
-rw-r--r-- | lib/pthreadpool/pthreadpool.c | 34 | ||||
-rw-r--r-- | lib/pthreadpool/pthreadpool.h | 17 | ||||
-rw-r--r-- | lib/pthreadpool/pthreadpool_sync.c | 5 |
3 files changed, 56 insertions, 0 deletions
diff --git a/lib/pthreadpool/pthreadpool.c b/lib/pthreadpool/pthreadpool.c index 528f4cdfd67..127e684c63e 100644 --- a/lib/pthreadpool/pthreadpool.c +++ b/lib/pthreadpool/pthreadpool.c @@ -112,10 +112,13 @@ struct pthreadpool { * where the forking thread will unlock it again. */ pthread_mutex_t fork_mutex; + + bool per_thread_cwd; }; static pthread_mutex_t pthreadpools_mutex = PTHREAD_MUTEX_INITIALIZER; static struct pthreadpool *pthreadpools = NULL; +static bool pthreadpool_support_thread_cwd = false; static pthread_once_t pthreadpool_atfork_initialized = PTHREAD_ONCE_INIT; static void pthreadpool_prep_atfork(void); @@ -182,6 +185,11 @@ int pthreadpool_init(unsigned max_threads, struct pthreadpool **presult, pool->max_threads = max_threads; pool->num_idle = 0; pool->prefork_cond = NULL; + if (max_threads != 0) { + pool->per_thread_cwd = pthreadpool_support_thread_cwd; + } else { + pool->per_thread_cwd = false; + } ret = pthread_mutex_lock(&pthreadpools_mutex); if (ret != 0) { @@ -241,6 +249,15 @@ size_t pthreadpool_queued_jobs(struct pthreadpool *pool) return ret; } +bool pthreadpool_per_thread_cwd(struct pthreadpool *pool) +{ + if (pool->stopped) { + return false; + } + + return pool->per_thread_cwd; +} + static void pthreadpool_prepare_pool(struct pthreadpool *pool) { int ret; @@ -359,6 +376,16 @@ static void pthreadpool_child(void) static void pthreadpool_prep_atfork(void) { +#ifdef HAVE_UNSHARE_CLONE_FS + int res; + + /* remember if unshare(CLONE_FS) works. */ + res = unshare(CLONE_FS); + if (res == 0) { + pthreadpool_support_thread_cwd = true; + } +#endif + pthread_atfork(pthreadpool_prepare, pthreadpool_parent, pthreadpool_child); } @@ -571,6 +598,13 @@ static void *pthreadpool_server(void *arg) struct pthreadpool *pool = (struct pthreadpool *)arg; int res; +#ifdef HAVE_UNSHARE_CLONE_FS + if (pool->per_thread_cwd) { + res = unshare(CLONE_FS); + assert(res == 0); + } +#endif + res = pthread_mutex_lock(&pool->mutex); if (res != 0) { return NULL; diff --git a/lib/pthreadpool/pthreadpool.h b/lib/pthreadpool/pthreadpool.h index b4733580e07..d8daf9e4519 100644 --- a/lib/pthreadpool/pthreadpool.h +++ b/lib/pthreadpool/pthreadpool.h @@ -72,6 +72,23 @@ size_t pthreadpool_max_threads(struct pthreadpool *pool); size_t pthreadpool_queued_jobs(struct pthreadpool *pool); /** + * @brief Check for per thread current working directory support of pthreadpool + * + * Since Linux kernel 2.6.16, unshare(CLONE_FS) is supported, + * which provides a per thread current working directory + * and allows [f]chdir() within the worker threads. + * + * Note that this doesn't work on some contraint container setups, + * the complete unshare() syscall might be rejected. + * pthreadpool_per_thread_cwd() returns what is available + * at runtime, so the callers should really check this! + * + * @param[in] pool The pool to run the job on + * @return supported: true, otherwise: false + */ +bool pthreadpool_per_thread_cwd(struct pthreadpool *pool); + +/** * @brief Stop a pthreadpool * * Stop a pthreadpool. If jobs are submitted, but not yet active in diff --git a/lib/pthreadpool/pthreadpool_sync.c b/lib/pthreadpool/pthreadpool_sync.c index 48e6a0ddb60..2ed6f36dbbc 100644 --- a/lib/pthreadpool/pthreadpool_sync.c +++ b/lib/pthreadpool/pthreadpool_sync.c @@ -65,6 +65,11 @@ size_t pthreadpool_queued_jobs(struct pthreadpool *pool) return 0; } +bool pthreadpool_per_thread_cwd(struct pthreadpool *pool) +{ + return false; +} + int pthreadpool_add_job(struct pthreadpool *pool, int job_id, void (*fn)(void *private_data), void *private_data) { |