From: Stefan Metzmacher Date: Fri, 11 Jan 2019 11:47:40 +0000 (+0100) Subject: s3:lib: add per_thread_cwd_{check,supported,disable,activate}() helper functions X-Git-Tag: talloc-2.1.15~205 X-Git-Url: http://git.samba.org/samba.git/?p=garming%2Fsamba-autobuild%2F.git;a=commitdiff_plain;h=92c2ed4db29c8fa4e5989b5f6d611752bdaa523d s3:lib: add per_thread_cwd_{check,supported,disable,activate}() helper functions Only Linux it's possible to have a per thread current working directory using unshare(CLONE_FS). Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme Reviewed-by: Volker Lendecke --- diff --git a/source3/include/proto.h b/source3/include/proto.h index 81065c893bb..715bc56e286 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -1008,4 +1008,11 @@ void contend_level2_oplocks_begin(files_struct *fsp, void contend_level2_oplocks_end(files_struct *fsp, enum level2_contention_type type); +/* The following definitions come from lib/per_thread_cwd.c */ + +void per_thread_cwd_check(void); +bool per_thread_cwd_supported(void); +void per_thread_cwd_disable(void); +void per_thread_cwd_activate(void); + #endif /* _PROTO_H_ */ diff --git a/source3/lib/per_thread_cwd.c b/source3/lib/per_thread_cwd.c new file mode 100644 index 00000000000..fcec572a759 --- /dev/null +++ b/source3/lib/per_thread_cwd.c @@ -0,0 +1,156 @@ +/* + Unix SMB/Netbios implementation. + + Copyright (C) Ralph Boehme 2019 + Copyright (C) Stefan Metzmacher 2019 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "system/filesys.h" +#include "system/threads.h" +#ifdef HAVE_UNSHARE_CLONE_FS +#include +#endif /* HAVE_UNSHARE_CLONE_FS */ + +static bool _per_thread_cwd_checked; +static bool _per_thread_cwd_supported; +#ifdef HAVE_UNSHARE_CLONE_FS +static __thread bool _per_thread_cwd_disabled; +static __thread bool _per_thread_cwd_activated; +#endif /* HAVE_UNSHARE_CLONE_FS */ + +/* + * This is the first function to be called! + * Typically in the main() function before + * any threads are created. + * + * This can be called multiple times + * as the result is cached the first time. + */ +void per_thread_cwd_check(void) +{ + if (_per_thread_cwd_checked) { + return; + } + +#ifdef HAVE_UNSHARE_CLONE_FS + /* + * While unshare(CLONE_FS) is available on + * Linux for ages, unshare() is also + * used to implement containers with various + * per container namespaces. + * + * It's possible that the whole unshare() + * is blocked in order to disallow neested + * containers. + * + * That's why we sadly need a runtime check + * for this. + */ + { + int res; + + res = unshare(CLONE_FS); + if (res == 0) { + _per_thread_cwd_supported = true; + } + } + + /* + * We're in the main thread, so we should disallow + * per_thread_cwd_activate() here. + */ + _per_thread_cwd_disabled = true; +#endif /* HAVE_UNSHARE_CLONE_FS */ + + _per_thread_cwd_checked = true; +} + +/* + * In order to use per_thread_cwd_supported() + * per_thread_cwd_check() needs to be called first! + * Otherwise an assert will be triggered! + */ +bool per_thread_cwd_supported(void) +{ + SMB_ASSERT(_per_thread_cwd_checked); + return _per_thread_cwd_supported; +} + +/* + * In order to use per_thread_cwd_disable() + * should be called after any fork() in order + * to mark the main thread of the process, + * which should disallow per_thread_cwd_activate(). + * + * This can be called without calling + * per_thread_cwd_check() first. + * + * And it can't be called after calling + * per_thread_cwd_activate()! + * Otherwise an assert will be triggered! + * + * This can be called multiple times + * as the result is cached the first time. + */ +void per_thread_cwd_disable(void) +{ +#ifdef HAVE_UNSHARE_CLONE_FS + SMB_ASSERT(!_per_thread_cwd_activated); + if (_per_thread_cwd_disabled) { + return; + } + _per_thread_cwd_disabled = true; +#endif /* HAVE_UNSHARE_CLONE_FS */ +} + +/* + * In order to use per_thread_cwd_activate() + * per_thread_cwd_supported() needs to be checked first! + * Otherwise an assert will be triggered! + * + * This MUST only be called within helper threads! + * + * That means it can't be called after calling + * per_thread_cwd_disable()! + * Otherwise an assert will be triggered! + * + * This can be called multiple times + * as the result is cached the first time. + */ +void per_thread_cwd_activate(void) +{ + SMB_ASSERT(_per_thread_cwd_checked); + SMB_ASSERT(_per_thread_cwd_supported); + +#ifdef HAVE_UNSHARE_CLONE_FS + if (_per_thread_cwd_activated) { + return; + } + + SMB_ASSERT(!_per_thread_cwd_disabled); + + { + int ret; + ret = unshare(CLONE_FS); + SMB_ASSERT(ret == 0); + } + + _per_thread_cwd_activated = true; +#else /* not HAVE_UNSHARE_CLONE_FS */ + smb_panic(__location__); +#endif /* not HAVE_UNSHARE_CLONE_FS */ +} diff --git a/source3/wscript_build b/source3/wscript_build index a8ea8e581df..f25a27ba3a8 100644 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -968,6 +968,7 @@ bld.SAMBA3_LIBRARY('samba3-util', lib/namearray.c lib/file_id.c lib/cbuf.c + lib/per_thread_cwd.c ''', deps=''' samba-util