summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2018-03-13 16:59:32 +0100
committerRalph Boehme <slow@samba.org>2018-07-24 17:38:27 +0200
commit65e4742d168454df6507d9e74993749063435dd6 (patch)
tree2b920630ffeb36972db502fe4da4c6bd06e07977 /lib
parent7cb27238fe4e6dfc45cf3128ccd4a392aaf4e877 (diff)
downloadsamba-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>
Diffstat (limited to 'lib')
-rw-r--r--lib/pthreadpool/pthreadpool.c34
-rw-r--r--lib/pthreadpool/pthreadpool.h17
-rw-r--r--lib/pthreadpool/pthreadpool_sync.c5
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)
{