[RFC] Simplify async path based VFS functions: remove tevent and pthreadpool_tevent wrappers

Stefan Metzmacher metze at samba.org
Fri Jan 11 15:30:05 UTC 2019


Am 07.01.19 um 18:49 schrieb Ralph Böhme via samba-technical:
> On Fri, Jan 04, 2019 at 03:06:30PM +0100, Ralph Böhme wrote:
>> Please review part1 and push if happy. Part2 is only included for
>> completeness.
> 
> currently working on an updated patchset based on feedback from Volker
> and metze. Stay tuned...

Here's an updated patchset the main changes are:

- We have generic per_thread_cwd_{check,supported,disable,activate}()
  functions
- We handle EGAIN from pthreadpool_tevent_job_recv() as
  it can be impossible to create new threads, this was done
  implicit in 4.9, but as the job needs to know if it
  can alter the current working directory without side effects
  we need to run.
- We make sure we only use per_thread_cwd_activate() only
  used if the threadpool has at least one thread configured,
  so it isn't a sync pool. We shouldn't do it if
  "aio max threads = 0".
- We calculate the absolute path in vfswrap_getxattrat_do_sync()
  using full_path_tos().
- We deprecated the tevent wrapper api

A pipeline is running here:
https://gitlab.com/samba-team/devel/samba/pipelines/43026374

We plan to push this one the pipeline reports success.

metze
-------------- next part --------------
From fa7b52fca478040571b05ad6fac0de54f1a025a1 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 16 Mar 2018 19:01:20 +0100
Subject: [PATCH 01/66] s3:lib: add root_unix_token()

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/include/proto.h |  1 +
 source3/lib/util.c      | 26 ++++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/source3/include/proto.h b/source3/include/proto.h
index c92d9921d6ec..81065c893bb8 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -415,6 +415,7 @@ bool map_open_params_to_ntcreate(const char *smb_base_fname,
 				 uint32_t *pcreate_options,
 				 uint32_t *pprivate_flags);
 struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok);
+struct security_unix_token *root_unix_token(TALLOC_CTX *mem_ctx);
 bool dir_check_ftype(uint32_t mode, uint32_t dirtype);
 
 /* The following definitions come from lib/util_builtin.c  */
diff --git a/source3/lib/util.c b/source3/lib/util.c
index a3fe7c8aea23..8ff330bcd26e 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -2143,6 +2143,32 @@ struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct securi
 	return cpy;
 }
 
+/****************************************************************************
+ Return a root token
+****************************************************************************/
+
+struct security_unix_token *root_unix_token(TALLOC_CTX *mem_ctx)
+{
+	struct security_unix_token *t = NULL;
+
+	t = talloc_zero(mem_ctx, struct security_unix_token);
+	if (t == NULL) {
+		return NULL;
+	}
+
+	/*
+	 * This is not needed, but lets make it explicit, not implicit.
+	 */
+	*t = (struct security_unix_token) {
+		.uid = 0,
+		.gid = 0,
+		.ngroups = 0,
+		.groups = NULL
+	};
+
+	return t;
+}
+
 /****************************************************************************
  Check that a file matches a particular file type.
 ****************************************************************************/
-- 
2.17.1


From 0e41802d1ea93bfdc18750dfe2382eea3ed5ad17 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 11 Jan 2019 12:47:40 +0100
Subject: [PATCH 02/66] 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 <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/include/proto.h      |   7 ++
 source3/lib/per_thread_cwd.c | 156 +++++++++++++++++++++++++++++++++++
 source3/wscript_build        |   1 +
 3 files changed, 164 insertions(+)
 create mode 100644 source3/lib/per_thread_cwd.c

diff --git a/source3/include/proto.h b/source3/include/proto.h
index 81065c893bb8..715bc56e2861 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 000000000000..fcec572a759c
--- /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 <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "system/threads.h"
+#ifdef HAVE_UNSHARE_CLONE_FS
+#include <sched.h>
+#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 a8ea8e581df2..f25a27ba3a8f 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
-- 
2.17.1


From f9d67be8066b427f67c18bdd0a27be02eff4b476 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 11 Jan 2019 13:13:04 +0100
Subject: [PATCH 03/66] s3:smbd: prepare the usage of per_thread_cwd_*()
 functions

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/util.c    | 7 +++++++
 source3/smbd/server.c | 7 +++++++
 2 files changed, 14 insertions(+)

diff --git a/source3/lib/util.c b/source3/lib/util.c
index 8ff330bcd26e..5dbd67349faf 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -453,6 +453,13 @@ NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
 	NTSTATUS status = NT_STATUS_OK;
 	int ret;
 
+	/*
+	 * The main process thread should never
+	 * allow per_thread_cwd_enable() to be
+	 * called.
+	 */
+	per_thread_cwd_disable();
+
 	if (reinit_after_fork_pipe[1] != -1) {
 		close(reinit_after_fork_pipe[1]);
 		reinit_after_fork_pipe[1] = -1;
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 871bb9234491..c59759fed985 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -1798,6 +1798,13 @@ extern void build_options(bool screen);
 		exit(1);
 	}
 
+	/*
+	 * This calls unshare(CLONE_FS); on linux
+	 * in order to check if the running kernel/container
+	 * environment supports it.
+	 */
+	per_thread_cwd_check();
+
 	if (!cluster_probe_ok()) {
 		exit(1);
 	}
-- 
2.17.1


From c0a4805d892569ddd9e483e59465f1218e213546 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Fri, 11 Jan 2019 13:15:58 +0100
Subject: [PATCH 04/66] s3:torture: call per_thread_cwd_check() in vfstest.c
 main()

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 source3/torture/vfstest.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/source3/torture/vfstest.c b/source3/torture/vfstest.c
index 0f80d11daae7..508b55568e8a 100644
--- a/source3/torture/vfstest.c
+++ b/source3/torture/vfstest.c
@@ -511,6 +511,8 @@ int main(int argc, const char *argv[])
 	   facilities.  See lib/debug.c */
 	setup_logging("vfstest", DEBUG_STDOUT);
 
+	per_thread_cwd_check();
+
 	set_smbd_shim(&vfstest_shim_fns);
 
 	/* Load command lists */
-- 
2.17.1


From 82ade4ca6699bbb2897b11729cf366a1130b9c8c Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 16:32:46 +0100
Subject: [PATCH 05/66] s3:smbd: let SMB_VFS_GETXATTRAT_SEND() do explicit
 impersonation

SMB_VFS_GETXATTRAT_SEND() gets passed a raw event context and the
default implementation uses that as well a raw threadpool. Impersonation
is done explicitly instead of by the tevent and pthreadpool wrappers.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 examples/VFS/skel_opaque.c            |   3 +-
 examples/VFS/skel_transparent.c       |   5 +-
 source3/include/vfs.h                 |   6 +-
 source3/include/vfs_macros.h          |   8 +-
 source3/modules/vfs_default.c         | 195 ++++++++++++++++++++------
 source3/modules/vfs_full_audit.c      |   5 +-
 source3/modules/vfs_not_implemented.c |   3 +-
 source3/modules/vfs_time_audit.c      |   5 +-
 source3/modules/vfs_xattr_tdb.c       |   3 +-
 source3/smbd/smb2_query_directory.c   |   6 +-
 source3/smbd/vfs.c                    |  17 +--
 11 files changed, 179 insertions(+), 77 deletions(-)

diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index 054de50197e3..b3cd83a3e42a 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -873,14 +873,13 @@ struct skel_getxattrat_state {
 
 static struct tevent_req *skel_getxattrat_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			const struct smb_filename *smb_fname,
 			const char *xattr_name,
 			size_t alloc_hint)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
 	struct tevent_req *req = NULL;
 	struct skel_getxattrat_state *state = NULL;
 
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index cff52fa185ef..4e9785778378 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -1094,14 +1094,13 @@ static void skel_getxattrat_done(struct tevent_req *subreq);
 
 static struct tevent_req *skel_getxattrat_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			const struct smb_filename *smb_fname,
 			const char *xattr_name,
 			size_t alloc_hint)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
 	struct tevent_req *req = NULL;
 	struct skel_getxattrat_state *state = NULL;
 	struct tevent_req *subreq = NULL;
@@ -1113,7 +1112,7 @@ static struct tevent_req *skel_getxattrat_send(
 	}
 
 	subreq = SMB_VFS_NEXT_GETXATTRAT_SEND(state,
-					      evg,
+					      ev,
 					      handle,
 					      dir_fsp,
 					      smb_fname,
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 4f3db6948964..83ae6399a4a4 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -969,7 +969,7 @@ struct vfs_fn_pointers {
 					size_t size);
 	struct tevent_req *(*getxattrat_send_fn)(
 				TALLOC_CTX *mem_ctx,
-				const struct smb_vfs_ev_glue *evg,
+				struct tevent_context *ev,
 				struct vfs_handle_struct *handle,
 				files_struct *dir_fsp,
 				const struct smb_filename *smb_fname,
@@ -1481,7 +1481,7 @@ ssize_t smb_vfs_call_getxattr(struct vfs_handle_struct *handle,
 				size_t size);
 struct tevent_req *smb_vfs_call_getxattrat_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			const struct smb_filename *smb_fname,
@@ -1910,7 +1910,7 @@ ssize_t vfs_not_implemented_getxattr(vfs_handle_struct *handle,
 				size_t size);
 struct tevent_req *vfs_not_implemented_getxattrat_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			const struct smb_filename *smb_fname,
diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h
index a13680c239e2..7a0f14ef08d4 100644
--- a/source3/include/vfs_macros.h
+++ b/source3/include/vfs_macros.h
@@ -515,18 +515,18 @@
 #define SMB_VFS_NEXT_GETXATTR(handle,smb_fname,name,value,size) \
 	smb_vfs_call_getxattr((handle)->next,(smb_fname),(name),(value),(size))
 
-#define SMB_VFS_GETXATTRAT_SEND(mem_ctx,evg,dir_fsp,smb_fname, \
+#define SMB_VFS_GETXATTRAT_SEND(mem_ctx,ev,dir_fsp,smb_fname, \
 				xattr_name, alloc_hint) \
-	smb_vfs_call_getxattrat_send((mem_ctx),(evg), \
+	smb_vfs_call_getxattrat_send((mem_ctx),(ev), \
 				     (dir_fsp)->conn->vfs_handles, \
 				     (dir_fsp),(smb_fname),(xattr_name), \
 				     (alloc_hint))
 #define SMB_VFS_GETXATTRAT_RECV(req, aio_state, mem_ctx, xattr_value) \
 	smb_vfs_call_getxattrat_recv((req),(aio_state),(mem_ctx),(xattr_value))
 
-#define SMB_VFS_NEXT_GETXATTRAT_SEND(mem_ctx,evg,handle,dir_fsp,smb_fname, \
+#define SMB_VFS_NEXT_GETXATTRAT_SEND(mem_ctx,ev,handle,dir_fsp,smb_fname, \
 				     xattr_name,alloc_hint) \
-	smb_vfs_call_getxattrat_send((mem_ctx),(evg), \
+	smb_vfs_call_getxattrat_send((mem_ctx),(ev), \
 				     (handle)->next, \
 				     (dir_fsp), (smb_fname),(xattr_name), \
 				     (alloc_hint))
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index b1c4acc482dd..f54f87dc5c93 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -1493,7 +1493,7 @@ struct vfswrap_get_dos_attributes_state {
 	struct vfs_aio_state aio_state;
 	connection_struct *conn;
 	TALLOC_CTX *mem_ctx;
-	const struct smb_vfs_ev_glue *evg;
+	struct tevent_context *ev;
 	files_struct *dir_fsp;
 	struct smb_filename *smb_fname;
 	uint32_t dosmode;
@@ -1509,7 +1509,7 @@ static struct tevent_req *vfswrap_get_dos_attributes_send(
 			files_struct *dir_fsp,
 			struct smb_filename *smb_fname)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
+	struct tevent_context *ev = dir_fsp->conn->sconn->raw_ev_ctx;
 	struct tevent_req *req = NULL;
 	struct tevent_req *subreq = NULL;
 	struct vfswrap_get_dos_attributes_state *state = NULL;
@@ -1523,13 +1523,13 @@ static struct tevent_req *vfswrap_get_dos_attributes_send(
 	*state = (struct vfswrap_get_dos_attributes_state) {
 		.conn = dir_fsp->conn,
 		.mem_ctx = mem_ctx,
-		.evg = evg,
+		.ev = ev,
 		.dir_fsp = dir_fsp,
 		.smb_fname = smb_fname,
 	};
 
 	subreq = SMB_VFS_GETXATTRAT_SEND(state,
-					 evg,
+					 ev,
 					 dir_fsp,
 					 smb_fname,
 					 SAMBA_XATTR_DOS_ATTRIB,
@@ -1562,8 +1562,6 @@ static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
 					     &blob.data);
 	TALLOC_FREE(subreq);
 	if (xattr_size == -1) {
-		const struct smb_vfs_ev_glue *root_evg = NULL;
-
 		status = map_nt_error_from_unix(state->aio_state.error);
 
 		if (state->as_root) {
@@ -1576,14 +1574,15 @@ static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq)
 		}
 
 		state->as_root = true;
-		root_evg = smb_vfs_ev_glue_get_root_glue(state->evg);
 
+		become_root();
 		subreq = SMB_VFS_GETXATTRAT_SEND(state,
-						 root_evg,
+						 state->ev,
 						 state->dir_fsp,
 						 state->smb_fname,
 						 SAMBA_XATTR_DOS_ATTRIB,
 						 sizeof(fstring));
+		unbecome_root();
 		if (tevent_req_nomem(subreq, req)) {
 			return;
 		}
@@ -2903,13 +2902,22 @@ static ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,
 }
 
 struct vfswrap_getxattrat_state {
-	int dirfd;
+	struct tevent_context *ev;
+	files_struct *dir_fsp;
+	const struct smb_filename *smb_fname;
+	struct tevent_req *req;
+
+	/*
+	 * The following variables are talloced off "state" which is protected
+	 * by a destructor and thus are guaranteed to be safe to be used in the
+	 * job function in the worker thread.
+	 */
 	char *name;
-	size_t xattr_bufsize;
 	const char *xattr_name;
-	ssize_t xattr_size;
 	uint8_t *xattr_value;
+	struct security_unix_token *token;
 
+	ssize_t xattr_size;
 	struct vfs_aio_state vfs_aio_state;
 	SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
 };
@@ -2920,23 +2928,26 @@ static int vfswrap_getxattrat_state_destructor(
 	return -1;
 }
 
-static void vfswrap_getxattrat_do(void *private_data);
+static void vfswrap_getxattrat_do_sync(struct tevent_req *req);
+static void vfswrap_getxattrat_do_async(void *private_data);
 static void vfswrap_getxattrat_done(struct tevent_req *subreq);
 
 static struct tevent_req *vfswrap_getxattrat_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			const struct smb_filename *smb_fname,
 			const char *xattr_name,
 			size_t alloc_hint)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
-	struct pthreadpool_tevent *tp = smb_vfs_ev_glue_tp_chdir_safe(evg);
 	struct tevent_req *req = NULL;
 	struct tevent_req *subreq = NULL;
 	struct vfswrap_getxattrat_state *state = NULL;
+	size_t max_threads = 0;
+	bool have_per_thread_cwd = false;
+	bool have_per_thread_creds = false;
+	bool do_async = false;
 
 	req = tevent_req_create(mem_ctx, &state,
 				struct vfswrap_getxattrat_state);
@@ -2944,19 +2955,49 @@ static struct tevent_req *vfswrap_getxattrat_send(
 		return NULL;
 	}
 	*state = (struct vfswrap_getxattrat_state) {
-		.dirfd = dir_fsp->fh->fd,
-		.xattr_bufsize = alloc_hint,
+		.ev = ev,
+		.dir_fsp = dir_fsp,
+		.smb_fname = smb_fname,
+		.req = req,
 	};
 
+	max_threads = pthreadpool_tevent_max_threads(dir_fsp->conn->sconn->pool);
+	if (max_threads >= 1) {
+		/*
+		 * We need a non sync threadpool!
+		 */
+		have_per_thread_cwd = per_thread_cwd_supported();
+	}
+#ifdef HAVE_LINUX_THREAD_CREDENTIALS
+	have_per_thread_creds = true;
+#endif
+	if (have_per_thread_cwd && have_per_thread_creds) {
+		do_async = true;
+	}
+
 	SMBPROFILE_BYTES_ASYNC_START(syscall_asys_getxattrat, profile_p,
 				     state->profile_bytes, 0);
 
-	if (state->dirfd == -1) {
+	if (dir_fsp->fh->fd == -1) {
 		DBG_ERR("Need a valid directory fd\n");
 		tevent_req_error(req, EINVAL);
 		return tevent_req_post(req, ev);
 	}
 
+	if (alloc_hint > 0) {
+		state->xattr_value = talloc_zero_array(state,
+						       uint8_t,
+						       alloc_hint);
+		if (tevent_req_nomem(state->xattr_value, req)) {
+			return tevent_req_post(req, ev);
+		}
+	}
+
+	if (!do_async) {
+		vfswrap_getxattrat_do_sync(req);
+		return tevent_req_post(req, ev);
+	}
+
 	/*
 	 * Now allocate all parameters from a memory context that won't go away
 	 * no matter what. These paremeters will get used in threads and we
@@ -2974,22 +3015,32 @@ static struct tevent_req *vfswrap_getxattrat_send(
 		return tevent_req_post(req, ev);
 	}
 
-	if (state->xattr_bufsize > 0) {
-		state->xattr_value = talloc_zero_array(state,
-						       uint8_t,
-						       state->xattr_bufsize);
-		if (tevent_req_nomem(state->xattr_value, req)) {
-			return tevent_req_post(req, ev);
-		}
+	/*
+	 * This is a hot codepath so at first glance one might think we should
+	 * somehow optimize away the token allocation and do a
+	 * talloc_reference() or similar black magic instead. But due to the
+	 * talloc_stackframe pool per SMB2 request this should be a simple copy
+	 * without a malloc in most cases.
+	 */
+	if (geteuid() == sec_initial_uid()) {
+		state->token = root_unix_token(state);
+	} else {
+		state->token = copy_unix_token(
+					state,
+					dir_fsp->conn->session_info->unix_token);
+	}
+	if (tevent_req_nomem(state->token, req)) {
+		return tevent_req_post(req, ev);
 	}
 
 	SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
 
-	subreq = pthreadpool_tevent_job_send(state,
-					     ev,
-					     tp,
-					     vfswrap_getxattrat_do,
-					     state);
+	subreq = pthreadpool_tevent_job_send(
+			state,
+			ev,
+			dir_fsp->conn->sconn->raw_thread_pool,
+			vfswrap_getxattrat_do_async,
+			state);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
@@ -3000,7 +3051,43 @@ static struct tevent_req *vfswrap_getxattrat_send(
 	return req;
 }
 
-static void vfswrap_getxattrat_do(void *private_data)
+static void vfswrap_getxattrat_do_sync(struct tevent_req *req)
+{
+	struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
+		req, struct vfswrap_getxattrat_state);
+	char *path = NULL;
+	char *tofree = NULL;
+	char pathbuf[PATH_MAX+1];
+	size_t pathlen;
+	int err;
+
+	pathlen = full_path_tos(state->dir_fsp->fsp_name->base_name,
+				state->smb_fname->base_name,
+				pathbuf,
+				sizeof(pathbuf),
+				&path,
+				&tofree);
+	if (pathlen == -1) {
+		tevent_req_error(req, ENOMEM);
+		return;
+	}
+
+	state->xattr_size = getxattr(path,
+				     state->xattr_name,
+				     state->xattr_value,
+				     talloc_array_length(state->xattr_value));
+	err = errno;
+	TALLOC_FREE(tofree);
+	if (state->xattr_size == -1) {
+		tevent_req_error(req, err);
+		return;
+	}
+
+	tevent_req_done(req);
+	return;
+}
+
+static void vfswrap_getxattrat_do_async(void *private_data)
 {
 	struct vfswrap_getxattrat_state *state = talloc_get_type_abort(
 		private_data, struct vfswrap_getxattrat_state);
@@ -3014,14 +3101,22 @@ static void vfswrap_getxattrat_do(void *private_data)
 	/*
 	 * Here we simulate a getxattrat()
 	 * call using fchdir();getxattr()
-	 *
-	 * We don't need to revert the directory
-	 * change as pthreadpool_tevent wrapper
-	 * handlers that.
 	 */
-	SMB_ASSERT(pthreadpool_tevent_current_job_per_thread_cwd());
 
-	ret = fchdir(state->dirfd);
+	per_thread_cwd_activate();
+
+	/* Become the correct credential on this thread. */
+	ret = set_thread_credentials(state->token->uid,
+				     state->token->gid,
+				     (size_t)state->token->ngroups,
+				     state->token->groups);
+	if (ret != 0) {
+		state->xattr_size = -1;
+		state->vfs_aio_state.error = errno;
+		goto end_profile;
+	}
+
+	ret = fchdir(state->dir_fsp->fh->fd);
 	if (ret == -1) {
 		state->xattr_size = -1;
 		state->vfs_aio_state.error = errno;
@@ -3031,7 +3126,7 @@ static void vfswrap_getxattrat_do(void *private_data)
 	state->xattr_size = getxattr(state->name,
 				     state->xattr_name,
 				     state->xattr_value,
-				     state->xattr_bufsize);
+				     talloc_array_length(state->xattr_value));
 	if (state->xattr_size == -1) {
 		state->vfs_aio_state.error = errno;
 	}
@@ -3049,12 +3144,34 @@ static void vfswrap_getxattrat_done(struct tevent_req *subreq)
 	struct vfswrap_getxattrat_state *state = tevent_req_data(
 		req, struct vfswrap_getxattrat_state);
 	int ret;
+	bool ok;
+
+	/*
+	 * Make sure we run as the user again
+	 */
+	ok = change_to_user(state->dir_fsp->conn,
+			    state->dir_fsp->vuid);
+	if (!ok) {
+		smb_panic("Can't change to user");
+		return;
+	}
 
 	ret = pthreadpool_tevent_job_recv(subreq);
 	TALLOC_FREE(subreq);
 	SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
 	talloc_set_destructor(state, NULL);
-	if (tevent_req_error(req, ret)) {
+	if (ret != 0) {
+		if (ret != EAGAIN) {
+			tevent_req_error(req, ret);
+			return;
+		}
+		/*
+		 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
+		 * means the lower level pthreadpool failed to create a new
+		 * thread. Fallback to sync processing in that case to allow
+		 * some progress for the client.
+		 */
+		vfswrap_getxattrat_do_sync(req);
 		return;
 	}
 
diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c
index bae08102b0e2..7dbb6e1e6281 100644
--- a/source3/modules/vfs_full_audit.c
+++ b/source3/modules/vfs_full_audit.c
@@ -2523,14 +2523,13 @@ static void smb_full_audit_getxattrat_done(struct tevent_req *subreq);
 
 static struct tevent_req *smb_full_audit_getxattrat_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			const struct smb_filename *smb_fname,
 			const char *xattr_name,
 			size_t alloc_hint)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
 	struct tevent_req *req = NULL;
 	struct tevent_req *subreq = NULL;
 	struct smb_full_audit_getxattrat_state *state = NULL;
@@ -2555,7 +2554,7 @@ static struct tevent_req *smb_full_audit_getxattrat_send(
 	};
 
 	subreq = SMB_VFS_NEXT_GETXATTRAT_SEND(state,
-					      evg,
+					      ev,
 					      handle,
 					      dir_fsp,
 					      smb_fname,
diff --git a/source3/modules/vfs_not_implemented.c b/source3/modules/vfs_not_implemented.c
index e20b7eb76ed9..d642a133c189 100644
--- a/source3/modules/vfs_not_implemented.c
+++ b/source3/modules/vfs_not_implemented.c
@@ -877,14 +877,13 @@ struct vfs_not_implemented_getxattrat_state {
 
 struct tevent_req *vfs_not_implemented_getxattrat_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			const struct smb_filename *smb_fname,
 			const char *xattr_name,
 			size_t alloc_hint)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
 	struct tevent_req *req = NULL;
 	struct vfs_not_implemented_getxattrat_state *state = NULL;
 
diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c
index aefea33d3054..5dd6032b6587 100644
--- a/source3/modules/vfs_time_audit.c
+++ b/source3/modules/vfs_time_audit.c
@@ -2456,14 +2456,13 @@ static void smb_time_audit_getxattrat_done(struct tevent_req *subreq);
 
 static struct tevent_req *smb_time_audit_getxattrat_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			const struct smb_filename *smb_fname,
 			const char *xattr_name,
 			size_t alloc_hint)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
 	struct tevent_req *req = NULL;
 	struct tevent_req *subreq = NULL;
 	struct smb_time_audit_getxattrat_state *state = NULL;
@@ -2480,7 +2479,7 @@ static struct tevent_req *smb_time_audit_getxattrat_send(
 	};
 
 	subreq = SMB_VFS_NEXT_GETXATTRAT_SEND(state,
-					      evg,
+					      ev,
 					      handle,
 					      dir_fsp,
 					      smb_fname,
diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c
index 32968ae083fa..037c40456323 100644
--- a/source3/modules/vfs_xattr_tdb.c
+++ b/source3/modules/vfs_xattr_tdb.c
@@ -112,14 +112,13 @@ struct xattr_tdb_getxattrat_state {
 
 static struct tevent_req *xattr_tdb_getxattrat_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			const struct smb_filename *smb_fname,
 			const char *xattr_name,
 			size_t alloc_hint)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
 	struct tevent_req *req = NULL;
 	struct xattr_tdb_getxattrat_state *state = NULL;
 	struct smb_filename *cwd = NULL;
diff --git a/source3/smbd/smb2_query_directory.c b/source3/smbd/smb2_query_directory.c
index 68c00241a510..654e21decc8d 100644
--- a/source3/smbd/smb2_query_directory.c
+++ b/source3/smbd/smb2_query_directory.c
@@ -240,7 +240,6 @@ struct smbd_smb2_query_directory_state {
 	bool async_dosmode;
 	bool async_ask_sharemode;
 	int last_entry_off;
-	struct pthreadpool_tevent *tp_chdir_safe;
 	size_t max_async_dosmode_active;
 	uint32_t async_dosmode_active;
 	bool done;
@@ -279,7 +278,6 @@ static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx,
 	}
 	state->evg = conn->user_vfs_evg;
 	state->ev = ev;
-	state->tp_chdir_safe = smb_vfs_ev_glue_tp_chdir_safe(state->evg);
 	state->fsp = fsp;
 	state->smb2req = smb2req;
 	state->in_output_buffer_length = in_output_buffer_length;
@@ -519,7 +517,7 @@ static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx,
 	if (state->async_dosmode) {
 		size_t max_threads;
 
-		max_threads = pthreadpool_tevent_max_threads(state->tp_chdir_safe);
+		max_threads = pthreadpool_tevent_max_threads(conn->sconn->raw_thread_pool);
 
 		state->max_async_dosmode_active = lp_smbd_max_async_dosmode(
 							SNUM(conn));
@@ -664,7 +662,7 @@ static bool smb2_query_directory_next_entry(struct tevent_req *req)
 		state->async_dosmode_active++;
 
 		outstanding_aio = pthreadpool_tevent_queued_jobs(
-					state->tp_chdir_safe);
+					state->fsp->conn->sconn->raw_thread_pool);
 
 		if (outstanding_aio > state->max_async_dosmode_active) {
 			stop = true;
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 351cd0a55671..7d46ec9273b3 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -3539,7 +3539,7 @@ static void smb_vfs_call_getxattrat_done(struct tevent_req *subreq);
 
 struct tevent_req *smb_vfs_call_getxattrat_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			const struct smb_filename *smb_fname,
@@ -3549,7 +3549,6 @@ struct tevent_req *smb_vfs_call_getxattrat_send(
 	struct tevent_req *req = NULL;
 	struct smb_vfs_call_getxattrat_state *state = NULL;
 	struct tevent_req *subreq = NULL;
-	bool ok;
 
 	req = tevent_req_create(mem_ctx, &state,
 				struct smb_vfs_call_getxattrat_state);
@@ -3560,24 +3559,18 @@ struct tevent_req *smb_vfs_call_getxattrat_send(
 	VFS_FIND(getxattrat_send);
 	state->recv_fn = handle->fns->getxattrat_recv_fn;
 
-	ok = smb_vfs_ev_glue_push_use(evg, req);
-	if (!ok) {
-		tevent_req_error(req, EIO);
-		return tevent_req_post(req, evg->return_ev);
-	}
-
 	subreq = handle->fns->getxattrat_send_fn(mem_ctx,
-						 evg->next_glue,
+						 ev,
 						 handle,
 						 dir_fsp,
 						 smb_fname,
 						 xattr_name,
 						 alloc_hint);
-	smb_vfs_ev_glue_pop_use(evg);
-
 	if (tevent_req_nomem(subreq, req)) {
-		return tevent_req_post(req, evg->return_ev);
+		return tevent_req_post(req, ev);
 	}
+	tevent_req_defer_callback(req, ev);
+
 	tevent_req_set_callback(subreq, smb_vfs_call_getxattrat_done, req);
 	return req;
 }
-- 
2.17.1


From 4a14511109e967f07e3df9902832de7eef9cd7f7 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 28 Dec 2018 12:12:20 +0100
Subject: [PATCH 06/66] s3:smbd: pass (raw) ev to
 SMB_VFS_GET_DOS_ATTRIBUTES_SEND() instead of smb_vfs_ev_glue

This also removes smb_vfs_ev_glue_[push|pop]_use() as the only caller
got removed.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 examples/VFS/skel_opaque.c            |  3 +-
 examples/VFS/skel_transparent.c       |  5 +--
 source3/include/vfs.h                 |  6 +--
 source3/modules/vfs_default.c         |  3 +-
 source3/modules/vfs_full_audit.c      |  5 +--
 source3/modules/vfs_not_implemented.c |  3 +-
 source3/modules/vfs_time_audit.c      |  5 +--
 source3/smbd/dosmode.c                |  5 ++-
 source3/smbd/vfs.c                    | 57 +++------------------------
 9 files changed, 20 insertions(+), 72 deletions(-)

diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index b3cd83a3e42a..6510ef30d6f5 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -714,12 +714,11 @@ struct skel_get_dos_attributes_state {
 
 static struct tevent_req *skel_get_dos_attributes_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			struct smb_filename *smb_fname)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
 	struct tevent_req *req = NULL;
 	struct skel_get_dos_attributes_state *state = NULL;
 
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index 4e9785778378..fc892a232082 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -895,12 +895,11 @@ static void skel_get_dos_attributes_done(struct tevent_req *subreq);
 
 static struct tevent_req *skel_get_dos_attributes_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			struct smb_filename *smb_fname)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
 	struct tevent_req *req = NULL;
 	struct skel_get_dos_attributes_state *state = NULL;
 	struct tevent_req *subreq = NULL;
@@ -912,7 +911,7 @@ static struct tevent_req *skel_get_dos_attributes_send(
 	}
 
 	subreq = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES_SEND(mem_ctx,
-						      evg,
+						      ev,
 						      handle,
 						      dir_fsp,
 						      smb_fname);
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 83ae6399a4a4..619c1a8eb94e 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -903,7 +903,7 @@ struct vfs_fn_pointers {
 
 	struct tevent_req *(*get_dos_attributes_send_fn)(
 				TALLOC_CTX *mem_ctx,
-				const struct smb_vfs_ev_glue *evg,
+				struct tevent_context *ev,
 				struct vfs_handle_struct *handle,
 				files_struct *dir_fsp,
 				struct smb_filename *smb_fname);
@@ -1370,7 +1370,7 @@ NTSTATUS smb_vfs_call_fset_dos_attributes(struct vfs_handle_struct *handle,
 					  uint32_t dosmode);
 struct tevent_req *smb_vfs_call_get_dos_attributes_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			struct smb_filename *smb_fname);
@@ -1852,7 +1852,7 @@ NTSTATUS vfs_not_implemented_get_dos_attributes(struct vfs_handle_struct *handle
 						uint32_t *dosmode);
 struct tevent_req *vfs_not_implemented_get_dos_attributes_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			struct smb_filename *smb_fname);
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index f54f87dc5c93..0a07d4069d75 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -1504,12 +1504,11 @@ static void vfswrap_get_dos_attributes_getxattr_done(struct tevent_req *subreq);
 
 static struct tevent_req *vfswrap_get_dos_attributes_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			struct smb_filename *smb_fname)
 {
-	struct tevent_context *ev = dir_fsp->conn->sconn->raw_ev_ctx;
 	struct tevent_req *req = NULL;
 	struct tevent_req *subreq = NULL;
 	struct vfswrap_get_dos_attributes_state *state = NULL;
diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c
index 7dbb6e1e6281..fcfb024d493a 100644
--- a/source3/modules/vfs_full_audit.c
+++ b/source3/modules/vfs_full_audit.c
@@ -2141,12 +2141,11 @@ static void smb_full_audit_get_dos_attributes_done(struct tevent_req *subreq);
 
 static struct tevent_req *smb_full_audit_get_dos_attributes_send(
 		TALLOC_CTX *mem_ctx,
-		const struct smb_vfs_ev_glue *evg,
+		struct tevent_context *ev,
 		struct vfs_handle_struct *handle,
 		files_struct *dir_fsp,
 		struct smb_filename *smb_fname)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
 	struct tevent_req *req = NULL;
 	struct smb_full_audit_get_dos_attributes_state *state = NULL;
 	struct tevent_req *subreq = NULL;
@@ -2169,7 +2168,7 @@ static struct tevent_req *smb_full_audit_get_dos_attributes_send(
 	};
 
 	subreq = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES_SEND(mem_ctx,
-						      evg,
+						      ev,
 						      handle,
 						      dir_fsp,
 						      smb_fname);
diff --git a/source3/modules/vfs_not_implemented.c b/source3/modules/vfs_not_implemented.c
index d642a133c189..214390204a5b 100644
--- a/source3/modules/vfs_not_implemented.c
+++ b/source3/modules/vfs_not_implemented.c
@@ -717,12 +717,11 @@ struct vfs_not_implemented_get_dos_attributes_state {
 
 struct tevent_req *vfs_not_implemented_get_dos_attributes_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			struct smb_filename *smb_fname)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
 	struct tevent_req *req = NULL;
 	struct vfs_not_implemented_get_dos_attributes_state *state = NULL;
 
diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c
index 5dd6032b6587..a89c6be9f71e 100644
--- a/source3/modules/vfs_time_audit.c
+++ b/source3/modules/vfs_time_audit.c
@@ -1768,12 +1768,11 @@ static void smb_time_audit_get_dos_attributes_done(struct tevent_req *subreq);
 
 static struct tevent_req *smb_time_audit_get_dos_attributes_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			struct smb_filename *smb_fname)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
 	struct tevent_req *req = NULL;
 	struct smb_time_audit_get_dos_attributes_state *state = NULL;
 	struct tevent_req *subreq = NULL;
@@ -1789,7 +1788,7 @@ static struct tevent_req *smb_time_audit_get_dos_attributes_send(
 	};
 
 	subreq = SMB_VFS_NEXT_GET_DOS_ATTRIBUTES_SEND(mem_ctx,
-						      evg,
+						      ev,
 						      handle,
 						      dir_fsp,
 						      smb_fname);
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 966679a2c9c4..52781ca5ab35 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -19,6 +19,7 @@
 */
 
 #include "includes.h"
+#include "globals.h"
 #include "system/filesys.h"
 #include "librpc/gen_ndr/ndr_xattr.h"
 #include "librpc/gen_ndr/ioctl.h"
@@ -764,7 +765,7 @@ struct tevent_req *dos_mode_at_send(TALLOC_CTX *mem_ctx,
 				    files_struct *dir_fsp,
 				    struct smb_filename *smb_fname)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
+	struct tevent_context *ev = dir_fsp->conn->sconn->raw_ev_ctx;
 	struct tevent_req *req = NULL;
 	struct dos_mode_at_state *state = NULL;
 	struct tevent_req *subreq = NULL;
@@ -788,7 +789,7 @@ struct tevent_req *dos_mode_at_send(TALLOC_CTX *mem_ctx,
 	}
 
 	subreq = SMB_VFS_GET_DOS_ATTRIBUTES_SEND(state,
-						 evg,
+						 ev,
 						 dir_fsp,
 						 smb_fname);
 	if (tevent_req_nomem(subreq, req)) {
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 7d46ec9273b3..0cf8f8caa1d5 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -2284,46 +2284,6 @@ struct smb_vfs_ev_glue *smb_vfs_ev_glue_create_switch(
 	return evg_u;
 }
 
-static bool smb_vfs_ev_glue_push_use(const struct smb_vfs_ev_glue *evg,
-				     struct tevent_req *req)
-{
-	if (evg->run_ev == evg->return_ev) {
-		/*
-		 * We're already in the correct
-		 * impersonation environment.
-		 */
-		return true;
-	}
-
-	/*
-	 * Make sure that our callers callback function
-	 * will be called in the return_ev environment.
-	 */
-	tevent_req_defer_callback(req, evg->return_ev);
-
-	/*
-	 * let the event context wrapper do
-	 * the required impersonation.
-	 */
-	return tevent_context_push_use(evg->run_ev);
-}
-
-static void smb_vfs_ev_glue_pop_use(const struct smb_vfs_ev_glue *evg)
-{
-	if (evg->run_ev == evg->return_ev) {
-		/*
-		 * smb_vfs_ev_glue_push_use() didn't
-		 * change the impersonation environment.
-		 */
-		return;
-	}
-
-	/*
-	 * undo the impersonation
-	 */
-	tevent_context_pop_use(evg->run_ev);
-}
-
 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
 			 const char *service, const char *user)
 {
@@ -3265,7 +3225,7 @@ static void smb_vfs_call_get_dos_attributes_done(struct tevent_req *subreq);
 
 struct tevent_req *smb_vfs_call_get_dos_attributes_send(
 			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct vfs_handle_struct *handle,
 			files_struct *dir_fsp,
 			struct smb_filename *smb_fname)
@@ -3273,7 +3233,6 @@ struct tevent_req *smb_vfs_call_get_dos_attributes_send(
 	struct tevent_req *req = NULL;
 	struct smb_vfs_call_get_dos_attributes_state *state = NULL;
 	struct tevent_req *subreq = NULL;
-	bool ok;
 
 	req = tevent_req_create(mem_ctx, &state,
 				struct smb_vfs_call_get_dos_attributes_state);
@@ -3284,22 +3243,16 @@ struct tevent_req *smb_vfs_call_get_dos_attributes_send(
 	VFS_FIND(get_dos_attributes_send);
 	state->recv_fn = handle->fns->get_dos_attributes_recv_fn;
 
-	ok = smb_vfs_ev_glue_push_use(evg, req);
-	if (!ok) {
-		tevent_req_error(req, EIO);
-		return tevent_req_post(req, evg->return_ev);
-	}
-
 	subreq = handle->fns->get_dos_attributes_send_fn(mem_ctx,
-							 evg->next_glue,
+							 ev,
 							 handle,
 							 dir_fsp,
 							 smb_fname);
-	smb_vfs_ev_glue_pop_use(evg);
-
 	if (tevent_req_nomem(subreq, req)) {
-		return tevent_req_post(req, evg->return_ev);
+		return tevent_req_post(req, ev);
 	}
+	tevent_req_defer_callback(req, ev);
+
 	tevent_req_set_callback(subreq,
 				smb_vfs_call_get_dos_attributes_done,
 				req);
-- 
2.17.1


From 2c178b9d9087c89bf54683456a5835d5c72bcf53 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 28 Dec 2018 12:16:27 +0100
Subject: [PATCH 07/66] s3:smbd: pass (raw) ev to dos_mode_at_send() instead of
 smb_vfs_ev_glue

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/dosmode.c              | 3 +--
 source3/smbd/proto.h                | 2 +-
 source3/smbd/smb2_query_directory.c | 4 ++--
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 52781ca5ab35..177fe68c8948 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -761,11 +761,10 @@ struct dos_mode_at_state {
 static void dos_mode_at_vfs_get_dosmode_done(struct tevent_req *subreq);
 
 struct tevent_req *dos_mode_at_send(TALLOC_CTX *mem_ctx,
-				    struct smb_vfs_ev_glue *evg,
+				    struct tevent_context *ev,
 				    files_struct *dir_fsp,
 				    struct smb_filename *smb_fname)
 {
-	struct tevent_context *ev = dir_fsp->conn->sconn->raw_ev_ctx;
 	struct tevent_req *req = NULL;
 	struct dos_mode_at_state *state = NULL;
 	struct tevent_req *subreq = NULL;
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index a74a79f7569e..2a56c1e43468 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -264,7 +264,7 @@ uint32_t dos_mode_msdfs(connection_struct *conn,
 		      const struct smb_filename *smb_fname);
 uint32_t dos_mode(connection_struct *conn, struct smb_filename *smb_fname);
 struct tevent_req *dos_mode_at_send(TALLOC_CTX *mem_ctx,
-				    struct smb_vfs_ev_glue *evg,
+				    struct tevent_context *ev,
 				    files_struct *dir_fsp,
 				    struct smb_filename *smb_fname);
 NTSTATUS dos_mode_at_recv(struct tevent_req *req, uint32_t *dosmode);
diff --git a/source3/smbd/smb2_query_directory.c b/source3/smbd/smb2_query_directory.c
index 654e21decc8d..48a818dfe9ce 100644
--- a/source3/smbd/smb2_query_directory.c
+++ b/source3/smbd/smb2_query_directory.c
@@ -970,7 +970,7 @@ static struct tevent_req *fetch_dos_mode_send(
 			uint32_t info_level,
 			uint8_t *entry_marshall_buf)
 {
-	struct tevent_context *ev = smb_vfs_ev_glue_ev_ctx(evg);
+	struct tevent_context *ev = dir_fsp->conn->sconn->raw_ev_ctx;
 	struct tevent_req *req = NULL;
 	struct fetch_dos_mode_state *state = NULL;
 	struct tevent_req *subreq = NULL;
@@ -987,7 +987,7 @@ static struct tevent_req *fetch_dos_mode_send(
 
 	state->smb_fname = talloc_move(state, smb_fname);
 
-	subreq = dos_mode_at_send(state, evg, dir_fsp, state->smb_fname);
+	subreq = dos_mode_at_send(state, ev, dir_fsp, state->smb_fname);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
-- 
2.17.1


From 34c63fe592569f952b7b12a9b7d1aac26a826c77 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 28 Dec 2018 12:19:08 +0100
Subject: [PATCH 08/66] s3:smbd: pass (raw) ev to fetch_dos_mode_send instead
 of smb_vfs_ev_glue

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/smb2_query_directory.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/source3/smbd/smb2_query_directory.c b/source3/smbd/smb2_query_directory.c
index 48a818dfe9ce..1a3447c3a828 100644
--- a/source3/smbd/smb2_query_directory.c
+++ b/source3/smbd/smb2_query_directory.c
@@ -208,7 +208,7 @@ static NTSTATUS fetch_write_time_recv(struct tevent_req *req);
 
 static struct tevent_req *fetch_dos_mode_send(
 	TALLOC_CTX *mem_ctx,
-	struct smb_vfs_ev_glue *evg,
+	struct tevent_context *ev,
 	struct files_struct *dir_fsp,
 	struct smb_filename **smb_fname,
 	uint32_t info_level,
@@ -217,7 +217,6 @@ static struct tevent_req *fetch_dos_mode_send(
 static NTSTATUS fetch_dos_mode_recv(struct tevent_req *req);
 
 struct smbd_smb2_query_directory_state {
-	struct smb_vfs_ev_glue *evg;
 	struct tevent_context *ev;
 	struct smbd_smb2_request *smb2req;
 	uint64_t async_sharemode_count;
@@ -276,8 +275,7 @@ static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx,
 	if (req == NULL) {
 		return NULL;
 	}
-	state->evg = conn->user_vfs_evg;
-	state->ev = ev;
+	state->ev = fsp->conn->sconn->raw_ev_ctx;
 	state->fsp = fsp;
 	state->smb2req = smb2req;
 	state->in_output_buffer_length = in_output_buffer_length;
@@ -647,7 +645,7 @@ static bool smb2_query_directory_next_entry(struct tevent_req *req)
 		buf = (uint8_t *)state->base_data + state->last_entry_off;
 
 		subreq = fetch_dos_mode_send(state,
-					     state->evg,
+					     state->ev,
 					     state->fsp,
 					     &smb_fname,
 					     state->info_level,
@@ -964,13 +962,12 @@ static void fetch_dos_mode_done(struct tevent_req *subreq);
 
 static struct tevent_req *fetch_dos_mode_send(
 			TALLOC_CTX *mem_ctx,
-			struct smb_vfs_ev_glue *evg,
+			struct tevent_context *ev,
 			struct files_struct *dir_fsp,
 			struct smb_filename **smb_fname,
 			uint32_t info_level,
 			uint8_t *entry_marshall_buf)
 {
-	struct tevent_context *ev = dir_fsp->conn->sconn->raw_ev_ctx;
 	struct tevent_req *req = NULL;
 	struct fetch_dos_mode_state *state = NULL;
 	struct tevent_req *subreq = NULL;
-- 
2.17.1


From 1bab79be8ab8186c3f3536ac516de66f1176fc69 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:12:10 +0100
Subject: [PATCH 09/66] Revert "pthreadpool: reset monitor_fd after calling
 tevent_fd_set_auto_close()"

This reverts commit f68b5ee75f002ed542a8423070fb01e3b0e83f65.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool_tevent.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c
index 12148f18123b..7088202d97ca 100644
--- a/lib/pthreadpool/pthreadpool_tevent.c
+++ b/lib/pthreadpool/pthreadpool_tevent.c
@@ -719,7 +719,6 @@ static int pthreadpool_tevent_register_ev(
 			return ENOMEM;
 		}
 		tevent_fd_set_auto_close(glue->fde);
-		monitor_fd = -1;
 	}
 
 	/*
-- 
2.17.1


From 62b0979473ef6c69718f8a95e44a9e0c2080ba18 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:12:34 +0100
Subject: [PATCH 10/66] Revert "pthreadpool: ignore the return value of
 poll(NULL, 0UL, 1)"

This reverts commit 6da0d68f49bbd82f5a08427779c9f5ebd6f755aa.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool_tevent.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c
index 7088202d97ca..b4a9786f231a 100644
--- a/lib/pthreadpool/pthreadpool_tevent.c
+++ b/lib/pthreadpool/pthreadpool_tevent.c
@@ -873,7 +873,7 @@ static void pthreadpool_tevent_job_orphan(struct pthreadpool_tevent_job *job)
 	 */
 	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
 	while (job->needs_fence.wrapper) {
-		(void)poll(NULL, 0, 1);
+		poll(NULL, 0, 1);
 		PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
 	}
 	job->wrapper = NULL;
@@ -903,7 +903,7 @@ static void pthreadpool_tevent_job_orphan(struct pthreadpool_tevent_job *job)
 		if (job->needs_fence.signaled) {
 			break;
 		}
-		(void)poll(NULL, 0, 1);
+		poll(NULL, 0, 1);
 		PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
 	}
 
-- 
2.17.1


From bf6c8e736494467aceb191f6e785832c9e83b21e Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:23:48 +0100
Subject: [PATCH 11/66] Revert "pthreadpool: we need to use
 pthreadpool_tevent_per_thread_cwd() on the callers pool"

This reverts commit ff863f2d98ac5e12073af824b794404c3d7198c5.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool_tevent.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c
index b4a9786f231a..f88f82d17d80 100644
--- a/lib/pthreadpool/pthreadpool_tevent.c
+++ b/lib/pthreadpool/pthreadpool_tevent.c
@@ -992,7 +992,6 @@ struct tevent_req *pthreadpool_tevent_job_send(
 	struct pthreadpool_tevent_job_state *state = NULL;
 	struct pthreadpool_tevent_job *job = NULL;
 	int ret;
-	struct pthreadpool_tevent *caller_pool = pool;
 	struct pthreadpool_tevent_wrapper *wrapper = pool->wrapper.ctx;
 
 	pthreadpool_tevent_cleanup_orphaned_jobs();
@@ -1038,7 +1037,7 @@ struct tevent_req *pthreadpool_tevent_job_send(
 		return tevent_req_post(req, ev);
 	}
 	PTHREAD_TEVENT_JOB_THREAD_FENCE_INIT(job);
-	job->per_thread_cwd = pthreadpool_tevent_per_thread_cwd(caller_pool);
+	job->per_thread_cwd = pthreadpool_tevent_per_thread_cwd(pool);
 	talloc_set_destructor(job, pthreadpool_tevent_job_destructor);
 	DLIST_ADD_END(job->pool->jobs, job);
 	job->state = state;
-- 
2.17.1


From 1211dc05dd50828ab11e5cea7443f1bd25c87cf6 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:24:51 +0100
Subject: [PATCH 12/66] Revert "vfs_aio_pthread: use event context and
 threadpool from user_vfs_evg"

This reverts commit cd37badc02b3e56f974168b28447444cd54ee541.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/modules/vfs_aio_pthread.c | 40 +++++++++++++++++--------------
 1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/source3/modules/vfs_aio_pthread.c b/source3/modules/vfs_aio_pthread.c
index cf5b7f61d5b0..da1ca534907f 100644
--- a/source3/modules/vfs_aio_pthread.c
+++ b/source3/modules/vfs_aio_pthread.c
@@ -51,6 +51,7 @@ struct aio_open_private_data {
 	const char *fname;
 	char *dname;
 	struct smbd_server_connection *sconn;
+	const struct security_unix_token *ux_tok;
 	uint64_t initial_allocation_size;
 	/* Returns. */
 	int ret_fd;
@@ -139,6 +140,16 @@ static void aio_open_worker(void *private_data)
 	struct aio_open_private_data *opd =
 		(struct aio_open_private_data *)private_data;
 
+	/* Become the correct credential on this thread. */
+	if (set_thread_credentials(opd->ux_tok->uid,
+				opd->ux_tok->gid,
+				(size_t)opd->ux_tok->ngroups,
+				opd->ux_tok->groups) != 0) {
+		opd->ret_fd = -1;
+		opd->ret_errno = errno;
+		return;
+	}
+
 	opd->ret_fd = openat(opd->dir_fd,
 			opd->fname,
 			opd->flags,
@@ -208,6 +219,13 @@ static struct aio_open_private_data *create_private_open_data(const files_struct
 	opd->sconn = fsp->conn->sconn;
 	opd->initial_allocation_size = fsp->initial_allocation_size;
 
+	/* Copy our current credentials. */
+	opd->ux_tok = copy_unix_token(opd, get_current_utok(fsp->conn));
+	if (opd->ux_tok == NULL) {
+		TALLOC_FREE(opd);
+		return NULL;
+	}
+
 	/*
 	 * Copy the parent directory name and the
 	 * relative path within it.
@@ -250,10 +268,6 @@ static int open_async(const files_struct *fsp,
 {
 	struct aio_open_private_data *opd = NULL;
 	struct tevent_req *subreq = NULL;
-	const struct smb_vfs_ev_glue *evg = NULL;
-	struct tevent_context *ev = NULL;
-	struct pthreadpool_tevent *tp = NULL;
-	uid_t uid = -1;
 
 	opd = create_private_open_data(fsp, flags, mode);
 	if (opd == NULL) {
@@ -261,20 +275,10 @@ static int open_async(const files_struct *fsp,
 		return -1;
 	}
 
-	evg = fsp->conn->user_vfs_evg;
-
-	uid = get_current_uid(fsp->conn);
-	if (uid == 0) {
-		/*
-		 * If we're already running as root,
-		 * so the root glue.
-		 */
-		evg = smb_vfs_ev_glue_get_root_glue(evg);
-	}
-	ev = smb_vfs_ev_glue_ev_ctx(fsp->conn->user_vfs_evg);
-	tp = smb_vfs_ev_glue_tp_path_safe(fsp->conn->user_vfs_evg);
-
-	subreq = pthreadpool_tevent_job_send(opd, ev, tp, aio_open_worker, opd);
+	subreq = pthreadpool_tevent_job_send(opd,
+					     fsp->conn->user_ev_ctx,
+					     fsp->conn->sconn->raw_thread_pool,
+					     aio_open_worker, opd);
 	if (subreq == NULL) {
 		return -1;
 	}
-- 
2.17.1


From 1fb062c31ddc471b31f243103ab74273100d7b48 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:25:32 +0100
Subject: [PATCH 13/66] Revert "s3: vfs: add user_vfs_evg to connection_struct"

This reverts commit 2dd95c1c38b9e1ce32d3d1081b6ec177910087a4.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/include/vfs.h          |   3 +-
 source3/modules/vfs_readonly.c |   2 +-
 source3/smbd/conn.c            |   8 +-
 source3/smbd/msdfs.c           |  68 +--
 source3/smbd/proto.h           |  13 -
 source3/smbd/uid.c             | 754 +--------------------------------
 6 files changed, 29 insertions(+), 819 deletions(-)

diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 619c1a8eb94e..6516869b24e2 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -407,7 +407,7 @@ typedef struct files_struct {
 
 struct vuid_cache_entry {
 	struct auth_session_info *session_info;
-	struct smb_vfs_ev_glue *user_vfs_evg;
+	struct tevent_context *user_ev_ctx;
 	uint64_t vuid; /* SMB2 compat */
 	bool read_only;
 	uint32_t share_access;
@@ -456,7 +456,6 @@ typedef struct connection_struct {
 	 */
 	struct auth_session_info *session_info;
 	struct tevent_context *user_ev_ctx;
-	struct smb_vfs_ev_glue *user_vfs_evg;
 
 	/*
 	 * If the "force group" parameter is set, this is the primary gid that
diff --git a/source3/modules/vfs_readonly.c b/source3/modules/vfs_readonly.c
index 37a9e806a156..e7e12747a222 100644
--- a/source3/modules/vfs_readonly.c
+++ b/source3/modules/vfs_readonly.c
@@ -84,7 +84,7 @@ static int readonly_connect(vfs_handle_struct *handle,
       for (i=0; i< VUID_CACHE_SIZE; i++) {
         struct vuid_cache_entry *ent = &conn->vuid_cache->array[i];
         ent->vuid = UID_FIELD_INVALID;
-        TALLOC_FREE(ent->user_vfs_evg);
+        TALLOC_FREE(ent->user_ev_ctx);
         TALLOC_FREE(ent->session_info);
         ent->read_only = false;
         ent->share_access = 0;
diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c
index d8dc1c27d427..cfff6404608f 100644
--- a/source3/smbd/conn.c
+++ b/source3/smbd/conn.c
@@ -95,12 +95,10 @@ static void conn_clear_vuid_cache(connection_struct *conn, uint64_t vuid)
 		if (ent->vuid == vuid) {
 			ent->vuid = UID_FIELD_INVALID;
 
-			conn->user_ev_ctx = NULL;
-
-			if (conn->user_vfs_evg == ent->user_vfs_evg) {
-				conn->user_vfs_evg = NULL;
+			if (conn->user_ev_ctx == ent->user_ev_ctx) {
+				conn->user_ev_ctx = NULL;
 			}
-			TALLOC_FREE(ent->user_vfs_evg);
+			TALLOC_FREE(ent->user_ev_ctx);
 
 			/*
 			 * We need to keep conn->session_info around
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index 880a02b0320b..9b0b2de27caa 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -253,10 +253,6 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx,
 	const char *vfs_user;
 	struct smbd_server_connection *sconn;
 	const char *servicename = lp_const_servicename(snum);
-	const struct security_unix_token *unix_token = NULL;
-	struct tevent_context *user_ev_ctx = NULL;
-	struct pthreadpool_tevent *user_tp_chdir_safe = NULL;
-	struct pthreadpool_tevent *root_tp_chdir_safe = NULL;
 	int ret;
 
 	sconn = talloc_zero(ctx, struct smbd_server_connection);
@@ -333,7 +329,6 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx,
 			TALLOC_FREE(conn);
 			return NT_STATUS_NO_MEMORY;
 		}
-		unix_token = conn->session_info->unix_token;
 		/* unix_info could be NULL in session_info */
 		if (conn->session_info->unix_info != NULL) {
 			vfs_user = conn->session_info->unix_info->unix_name;
@@ -345,10 +340,6 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx,
 		vfs_user = get_current_username();
 	}
 
-	if (unix_token == NULL) {
-		unix_token = get_current_utok(conn);
-	}
-
 	/*
 	 * The impersonation has to be done by the caller
 	 * of create_conn_struct_tos[_cwd]().
@@ -362,63 +353,12 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx,
 	 * to avoid crashes because TALLOC_FREE(conn->user_ev_ctx)
 	 * would also remove sconn->raw_ev_ctx.
 	 */
-	user_ev_ctx = smbd_impersonate_debug_create(sconn->raw_ev_ctx,
-						    "FAKE impersonation",
-						    DBGLVL_DEBUG);
-	if (user_ev_ctx == NULL) {
-		TALLOC_FREE(conn);
-		return NT_STATUS_NO_MEMORY;
-	}
-	SMB_ASSERT(talloc_reparent(sconn->raw_ev_ctx, conn, user_ev_ctx));
-
-	user_tp_chdir_safe = smbd_impersonate_tp_current_create(conn,
-						sconn->sync_thread_pool,
-						conn,
-						conn->vuid,
-						true, /* chdir_safe */
-						unix_token);
-	if (user_tp_chdir_safe == NULL) {
-		TALLOC_FREE(conn);
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	root_tp_chdir_safe = smbd_impersonate_tp_become_create(conn,
-						sconn->sync_thread_pool,
-						true, /* chdir_safe */
-						become_root,
-						unbecome_root);
-	if (root_tp_chdir_safe == NULL) {
-		TALLOC_FREE(conn);
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	/*
-	 * We only use the chdir_safe wrappers
-	 * for everything in order to keep
-	 * it simple.
-	 */
-	conn->user_vfs_evg = smb_vfs_ev_glue_create(conn,
-						    user_ev_ctx,
-						    user_tp_chdir_safe,
-						    user_tp_chdir_safe,
-						    user_tp_chdir_safe,
-						    sconn->root_ev_ctx,
-						    root_tp_chdir_safe,
-						    root_tp_chdir_safe,
-						    root_tp_chdir_safe);
-	if (conn->user_vfs_evg == NULL) {
-		TALLOC_FREE(conn);
-		return NT_STATUS_NO_MEMORY;
-	}
-
-	SMB_ASSERT(talloc_reparent(conn, conn->user_vfs_evg, user_ev_ctx));
-	SMB_ASSERT(talloc_reparent(conn, conn->user_vfs_evg, user_tp_chdir_safe));
-	SMB_ASSERT(talloc_reparent(conn, conn->user_vfs_evg, root_tp_chdir_safe));
-
-	conn->user_ev_ctx = smb_vfs_ev_glue_ev_ctx(conn->user_vfs_evg);
+	conn->user_ev_ctx = smbd_impersonate_debug_create(sconn->raw_ev_ctx,
+							  "FAKE impersonation",
+							  DBGLVL_DEBUG);
 	if (conn->user_ev_ctx == NULL) {
 		TALLOC_FREE(conn);
-		return NT_STATUS_INTERNAL_ERROR;
+		return NT_STATUS_NO_MEMORY;
 	}
 
 	set_conn_connectpath(conn, connpath);
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 2a56c1e43468..eb35a94862ac 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -1255,19 +1255,6 @@ struct tevent_context *smbd_impersonate_conn_sess_create(
 struct tevent_context *smbd_impersonate_root_create(struct tevent_context *main_ev);
 struct tevent_context *smbd_impersonate_guest_create(struct tevent_context *main_ev);
 
-struct pthreadpool_tevent *smbd_impersonate_tp_current_create(
-				TALLOC_CTX *mem_ctx,
-				struct pthreadpool_tevent *sync_tp,
-				struct connection_struct *conn,
-				uint64_t vuid, bool chdir_safe,
-				const struct security_unix_token *unix_token);
-struct pthreadpool_tevent *smbd_impersonate_tp_become_create(
-					TALLOC_CTX *mem_ctx,
-					struct pthreadpool_tevent *sync_tp,
-					bool chdir_safe,
-					void (*become_fn)(void),
-					void (*unbecome_fn)(void));
-
 /* The following definitions come from smbd/utmp.c  */
 
 void sys_utmp_claim(const char *username, const char *hostname,
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index 77e5f8c83b71..0518e5254a8e 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -18,7 +18,6 @@
 */
 
 #include "includes.h"
-#include "system/filesys.h"
 #include "system/passwd.h"
 #include "smbd/smbd.h"
 #include "smbd/globals.h"
@@ -28,12 +27,6 @@
 #include "auth.h"
 #include "../auth/auth_util.h"
 #include "lib/util/time_basic.h"
-#include "lib/pthreadpool/pthreadpool_tevent.h"
-
-static struct smb_vfs_ev_glue *smbd_impersonate_user_ev_glue_create(
-				struct connection_struct *conn,
-				uint64_t vuid,
-				struct auth_session_info *session_info);
 
 struct smbd_impersonate_debug_state {
 	int dbg_lvl;
@@ -314,8 +307,7 @@ static void free_conn_session_info_if_unused(connection_struct *conn)
 		}
 	}
 	/* Not used, safe to free. */
-	conn->user_ev_ctx = NULL;
-	TALLOC_FREE(conn->user_vfs_evg);
+	TALLOC_FREE(conn->user_ev_ctx);
 	TALLOC_FREE(conn->session_info);
 }
 
@@ -441,13 +433,10 @@ static bool check_user_ok(connection_struct *conn,
 			}
 			free_conn_session_info_if_unused(conn);
 			conn->session_info = ent->session_info;
-			conn->user_vfs_evg = ent->user_vfs_evg;
+			conn->user_ev_ctx = ent->user_ev_ctx;
 			conn->read_only = ent->read_only;
 			conn->share_access = ent->share_access;
 			conn->vuid = ent->vuid;
-			conn->user_ev_ctx = smb_vfs_ev_glue_ev_ctx(
-						conn->user_vfs_evg);
-			SMB_ASSERT(conn->user_ev_ctx != NULL);
 			return(True);
 		}
 	}
@@ -493,12 +482,22 @@ static bool check_user_ok(connection_struct *conn,
 		ent->session_info->unix_token->uid = sec_initial_uid();
 	}
 
-	ent->user_vfs_evg = smbd_impersonate_user_ev_glue_create(conn,
-							vuid, ent->session_info);
-	if (ent->user_vfs_evg == NULL) {
-		TALLOC_FREE(ent->session_info);
-		ent->vuid = UID_FIELD_INVALID;
-		return false;
+	if (vuid == UID_FIELD_INVALID) {
+		ent->user_ev_ctx = smbd_impersonate_conn_sess_create(
+			conn->sconn->raw_ev_ctx, conn, ent->session_info);
+		if (ent->user_ev_ctx == NULL) {
+			TALLOC_FREE(ent->session_info);
+			ent->vuid = UID_FIELD_INVALID;
+			return false;
+		}
+	} else {
+		ent->user_ev_ctx = smbd_impersonate_conn_vuid_create(
+			conn->sconn->raw_ev_ctx, conn, vuid);
+		if (ent->user_ev_ctx == NULL) {
+			TALLOC_FREE(ent->session_info);
+			ent->vuid = UID_FIELD_INVALID;
+			return false;
+		}
 	}
 
 	/*
@@ -513,10 +512,7 @@ static bool check_user_ok(connection_struct *conn,
 	free_conn_session_info_if_unused(conn);
 	conn->session_info = ent->session_info;
 	conn->vuid = ent->vuid;
-	conn->user_vfs_evg = ent->user_vfs_evg;
-	conn->user_ev_ctx = smb_vfs_ev_glue_ev_ctx(conn->user_vfs_evg);
-	SMB_ASSERT(conn->user_ev_ctx != NULL);
-
+	conn->user_ev_ctx = ent->user_ev_ctx;
 	if (vuid == UID_FIELD_INVALID) {
 		/*
 		 * Not strictly needed, just make it really
@@ -525,7 +521,7 @@ static bool check_user_ok(connection_struct *conn,
 		ent->read_only = false;
 		ent->share_access = 0;
 		ent->session_info = NULL;
-		ent->user_vfs_evg = NULL;
+		ent->user_ev_ctx = NULL;
 	}
 
 	conn->read_only = readonly_share;
@@ -1937,713 +1933,3 @@ struct tevent_context *smbd_impersonate_guest_create(struct tevent_context *main
 
 	return ev;
 }
-
-struct smbd_impersonate_tp_current_state {
-	const void *conn_ptr;
-	uint64_t vuid; /* SMB2 compat */
-	struct security_unix_token partial_ut;
-	bool chdir_safe;
-	int saved_cwd_fd;
-};
-
-static int smbd_impersonate_tp_current_state_destructor(
-		struct smbd_impersonate_tp_current_state *state)
-{
-	if (state->saved_cwd_fd != -1) {
-		smb_panic(__location__);
-	}
-
-	return 0;
-}
-
-static bool smbd_impersonate_tp_current_before_job(struct pthreadpool_tevent *wrap,
-						   void *private_data,
-						   struct pthreadpool_tevent *main,
-						   const char *location)
-{
-	struct smbd_impersonate_tp_current_state *state =
-		talloc_get_type_abort(private_data,
-		struct smbd_impersonate_tp_current_state);
-
-	if (state->conn_ptr != current_user.conn) {
-		smb_panic(__location__);
-	}
-
-	if (state->vuid != current_user.vuid) {
-		smb_panic(__location__);
-	}
-
-	if (state->partial_ut.uid != current_user.ut.uid) {
-		smb_panic(__location__);
-	}
-
-	if (state->partial_ut.gid != current_user.ut.gid) {
-		smb_panic(__location__);
-	}
-
-	if (state->partial_ut.ngroups != current_user.ut.ngroups) {
-		smb_panic(__location__);
-	}
-
-	/*
-	 * We don't verify the group list, we should have hit
-	 * an assert before. We only want to catch programmer
-	 * errors here!
-	 *
-	 * We just have a sync pool and want to make sure
-	 * we're already in the correct state.
-	 *
-	 * So we don't do any active impersonation.
-	 */
-
-	/*
-	 * we may need to remember the current working directory
-	 * and later restore it in the after_job hook.
-	 */
-	if (state->chdir_safe) {
-		int open_flags = O_RDONLY;
-		bool ok;
-
-#ifdef O_DIRECTORY
-		open_flags |= O_DIRECTORY;
-#endif
-#ifdef O_CLOEXEC
-		open_flags |= O_CLOEXEC;
-#endif
-
-		state->saved_cwd_fd = open(".", open_flags);
-		if (state->saved_cwd_fd == -1) {
-			DBG_ERR("unable to open '.' with open_flags[0x%x] - %s\n",
-				open_flags, strerror(errno));
-			smb_panic("smbd_impersonate_tp_current_before_job: "
-				  "unable to open cwd '.'");
-			return false;
-		}
-		ok = smb_set_close_on_exec(state->saved_cwd_fd);
-		SMB_ASSERT(ok);
-	}
-
-	return true;
-}
-
-static bool smbd_impersonate_tp_current_after_job(struct pthreadpool_tevent *wrap,
-						  void *private_data,
-						  struct pthreadpool_tevent *main,
-						  const char *location)
-{
-	struct smbd_impersonate_tp_current_state *state =
-		talloc_get_type_abort(private_data,
-		struct smbd_impersonate_tp_current_state);
-	int ret;
-
-	/*
-	 * There's no impersonation to revert.
-	 *
-	 * But we may need to reset the current working directory.
-	 */
-	if (state->saved_cwd_fd == -1) {
-		return true;
-	}
-
-	ret = fchdir(state->saved_cwd_fd);
-	if (ret != 0) {
-		DBG_ERR("unable to fchdir to the original directory - %s\n",
-			strerror(errno));
-		smb_panic("smbd_impersonate_tp_current_after_job: "
-			  "unable restore cwd with fchdir.");
-		return false;
-	}
-
-	close(state->saved_cwd_fd);
-	state->saved_cwd_fd = -1;
-
-	return true;
-}
-
-static const struct pthreadpool_tevent_wrapper_ops smbd_impersonate_tp_current_ops = {
-	.name		= "smbd_impersonate_tp_current",
-	.before_job	= smbd_impersonate_tp_current_before_job,
-	.after_job	= smbd_impersonate_tp_current_after_job,
-};
-
-struct pthreadpool_tevent *smbd_impersonate_tp_current_create(
-				TALLOC_CTX *mem_ctx,
-				struct pthreadpool_tevent *sync_tp,
-				struct connection_struct *conn,
-				uint64_t vuid, bool chdir_safe,
-				const struct security_unix_token *unix_token)
-{
-	struct pthreadpool_tevent *wrap_tp = NULL;
-	struct smbd_impersonate_tp_current_state *state = NULL;
-	size_t max_threads;
-
-	max_threads = pthreadpool_tevent_max_threads(sync_tp);
-	SMB_ASSERT(max_threads == 0);
-
-	/*
-	 * We have a fake threadpool without real threads.
-	 * So we just provide a a wrapper that asserts that
-	 * we are already in the required impersonation state.
-	 */
-
-	wrap_tp = pthreadpool_tevent_wrapper_create(sync_tp,
-					mem_ctx,
-					&smbd_impersonate_tp_current_ops,
-					&state,
-					struct smbd_impersonate_tp_current_state);
-	if (wrap_tp == NULL) {
-		return NULL;
-	}
-
-	state->conn_ptr = conn;
-	state->vuid = vuid;
-	state->partial_ut = *unix_token;
-	state->partial_ut.groups = NULL;
-	state->chdir_safe = chdir_safe;
-	state->saved_cwd_fd = -1;
-
-	if (chdir_safe) {
-		pthreadpool_tevent_force_per_thread_cwd(wrap_tp, state);
-	}
-
-	talloc_set_destructor(state, smbd_impersonate_tp_current_state_destructor);
-
-	return wrap_tp;
-}
-
-struct smbd_impersonate_tp_sess_state {
-	const struct security_unix_token *unix_token;
-};
-
-static bool smbd_impersonate_tp_sess_before_job(struct pthreadpool_tevent *wrap,
-						void *private_data,
-						struct pthreadpool_tevent *main,
-						const char *location)
-{
-	struct smbd_impersonate_tp_sess_state *state =
-		talloc_get_type_abort(private_data,
-		struct smbd_impersonate_tp_sess_state);
-	int ret;
-
-	/* Become the correct credential on this thread. */
-	ret = set_thread_credentials(state->unix_token->uid,
-				     state->unix_token->gid,
-				     (size_t)state->unix_token->ngroups,
-				     state->unix_token->groups);
-	if (ret != 0) {
-		return false;
-	}
-
-	return true;
-}
-
-static bool smbd_impersonate_tp_sess_after_job(struct pthreadpool_tevent *wrap,
-					       void *private_data,
-					       struct pthreadpool_tevent *main,
-					       const char *location)
-{
-	/*
-	 * We skip the 'unbecome' here, if the following
-	 * job cares, it already called set_thread_credentials() again.
-	 *
-	 * fd based jobs on the raw pool, don't really care...
-	 */
-	return true;
-}
-
-static const struct pthreadpool_tevent_wrapper_ops smbd_impersonate_tp_sess_ops = {
-	.name		= "smbd_impersonate_tp_sess",
-	.before_job	= smbd_impersonate_tp_sess_before_job,
-	.after_job	= smbd_impersonate_tp_sess_after_job,
-};
-
-static struct pthreadpool_tevent *smbd_impersonate_tp_sess_create(
-				TALLOC_CTX *mem_ctx,
-				struct pthreadpool_tevent *main_tp,
-				struct auth_session_info *session_info)
-{
-	struct pthreadpool_tevent *wrap_tp = NULL;
-	struct smbd_impersonate_tp_sess_state *state = NULL;
-	size_t max_threads;
-
-	max_threads = pthreadpool_tevent_max_threads(main_tp);
-	SMB_ASSERT(max_threads > 0);
-
-	wrap_tp = pthreadpool_tevent_wrapper_create(main_tp,
-					mem_ctx,
-					&smbd_impersonate_tp_sess_ops,
-					&state,
-					struct smbd_impersonate_tp_sess_state);
-	if (wrap_tp == NULL) {
-		return NULL;
-	}
-
-	state->unix_token = copy_unix_token(state, session_info->unix_token);
-	if (state->unix_token == NULL) {
-		int saved_errno = errno;
-		TALLOC_FREE(wrap_tp);
-		errno = saved_errno;
-		return NULL;
-	}
-
-	return wrap_tp;
-}
-
-struct smbd_impersonate_tp_become_state {
-	void (*become_fn)(void);
-	void (*unbecome_fn)(void);
-	bool chdir_safe;
-	int saved_cwd_fd;
-};
-
-static int smbd_impersonate_tp_become_state_destructor(
-		struct smbd_impersonate_tp_become_state *state)
-{
-	if (state->saved_cwd_fd != -1) {
-		smb_panic(__location__);
-	}
-
-	return 0;
-}
-
-
-static bool smbd_impersonate_tp_become_before_job(struct pthreadpool_tevent *wrap,
-						   void *private_data,
-						   struct pthreadpool_tevent *main,
-						   const char *location)
-{
-	struct smbd_impersonate_tp_become_state *state =
-		talloc_get_type_abort(private_data,
-		struct smbd_impersonate_tp_become_state);
-
-	/*
-	 * we may need to remember the current working directory
-	 * and later restore it in the after_job hook.
-	 */
-	if (state->chdir_safe) {
-		int open_flags = O_RDONLY;
-		bool ok;
-
-#ifdef O_DIRECTORY
-		open_flags |= O_DIRECTORY;
-#endif
-#ifdef O_CLOEXEC
-		open_flags |= O_CLOEXEC;
-#endif
-
-		state->saved_cwd_fd = open(".", open_flags);
-		if (state->saved_cwd_fd == -1) {
-			DBG_ERR("unable to open '.' with open_flags[0x%x] - %s\n",
-				open_flags, strerror(errno));
-			smb_panic("smbd_impersonate_tp_current_before_job: "
-				  "unable to open cwd '.'");
-			return false;
-		}
-		ok = smb_set_close_on_exec(state->saved_cwd_fd);
-		SMB_ASSERT(ok);
-	}
-
-	/*
-	 * The function should abort on error...
-	 */
-	state->become_fn();
-
-	return true;
-}
-
-static bool smbd_impersonate_tp_become_after_job(struct pthreadpool_tevent *wrap,
-						  void *private_data,
-						  struct pthreadpool_tevent *main,
-						  const char *location)
-{
-	struct smbd_impersonate_tp_become_state *state =
-		talloc_get_type_abort(private_data,
-		struct smbd_impersonate_tp_become_state);
-	int ret;
-
-	/*
-	 * The function should abort on error...
-	 */
-	state->unbecome_fn();
-
-	/*
-	 * There's no impersonation to revert.
-	 *
-	 * But we may need to reset the current working directory.
-	 */
-	if (state->saved_cwd_fd == -1) {
-		return true;
-	}
-
-	ret = fchdir(state->saved_cwd_fd);
-	if (ret != 0) {
-		DBG_ERR("unable to fchdir to the original directory - %s\n",
-			strerror(errno));
-		smb_panic("smbd_impersonate_tp_current_after_job: "
-			  "unable restore cwd with fchdir.");
-		return false;
-	}
-
-	close(state->saved_cwd_fd);
-	state->saved_cwd_fd = -1;
-
-	return true;
-}
-
-static const struct pthreadpool_tevent_wrapper_ops smbd_impersonate_tp_become_ops = {
-	.name		= "smbd_impersonate_tp_become",
-	.before_job	= smbd_impersonate_tp_become_before_job,
-	.after_job	= smbd_impersonate_tp_become_after_job,
-};
-
-struct pthreadpool_tevent *smbd_impersonate_tp_become_create(
-					TALLOC_CTX *mem_ctx,
-					struct pthreadpool_tevent *sync_tp,
-					bool chdir_safe,
-					void (*become_fn)(void),
-					void (*unbecome_fn)(void))
-{
-	struct pthreadpool_tevent *wrap_tp = NULL;
-	struct smbd_impersonate_tp_become_state *state = NULL;
-	size_t max_threads;
-
-	max_threads = pthreadpool_tevent_max_threads(sync_tp);
-	SMB_ASSERT(max_threads == 0);
-
-	/*
-	 * We have a fake threadpool without real threads.
-	 * So we just provide a a wrapper that asserts that
-	 * we are already in the required impersonation state.
-	 */
-
-	wrap_tp = pthreadpool_tevent_wrapper_create(sync_tp,
-					mem_ctx,
-					&smbd_impersonate_tp_become_ops,
-					&state,
-					struct smbd_impersonate_tp_become_state);
-	if (wrap_tp == NULL) {
-		return NULL;
-	}
-
-	state->become_fn = become_fn;
-	state->unbecome_fn = unbecome_fn;
-	state->chdir_safe = chdir_safe;
-	state->saved_cwd_fd = -1;
-
-	if (chdir_safe) {
-		pthreadpool_tevent_force_per_thread_cwd(wrap_tp, state);
-	}
-
-	talloc_set_destructor(state, smbd_impersonate_tp_become_state_destructor);
-
-	return wrap_tp;
-}
-
-struct smbd_impersonate_tp_root_state {
-	const struct security_unix_token *fallback_token;
-};
-
-static bool smbd_impersonate_tp_root_before_job(struct pthreadpool_tevent *wrap,
-						void *private_data,
-						struct pthreadpool_tevent *main,
-						const char *location)
-{
-	int ret;
-
-	/*
-	 * Become root in this thread.
-	 */
-	ret = set_thread_credentials(0, 0, 0, NULL);
-	if (ret != 0) {
-		return false;
-	}
-
-	return true;
-}
-
-static bool smbd_impersonate_tp_root_after_job(struct pthreadpool_tevent *wrap,
-					       void *private_data,
-					       struct pthreadpool_tevent *main,
-					       const char *location)
-{
-	struct smbd_impersonate_tp_root_state *state =
-		talloc_get_type_abort(private_data,
-		struct smbd_impersonate_tp_root_state);
-	int ret;
-
-	/*
-	 * Move to a non root token again.
-	 * We just use the one of the user_ev_ctx.
-	 *
-	 * The main goal is that we don't leave
-	 * a thread arround with a root token.
-	 */
-	ret = set_thread_credentials(state->fallback_token->uid,
-				     state->fallback_token->gid,
-				     (size_t)state->fallback_token->ngroups,
-				     state->fallback_token->groups);
-	if (ret != 0) {
-		return false;
-	}
-
-	return true;
-}
-
-static const struct pthreadpool_tevent_wrapper_ops smbd_impersonate_tp_root_ops = {
-	.name		= "smbd_impersonate_tp_root",
-	.before_job	= smbd_impersonate_tp_root_before_job,
-	.after_job	= smbd_impersonate_tp_root_after_job,
-};
-
-static struct pthreadpool_tevent *smbd_impersonate_tp_root_create(
-				TALLOC_CTX *mem_ctx,
-				struct pthreadpool_tevent *main_tp,
-				int snum,
-				const struct security_unix_token *fallback_token)
-{
-	struct pthreadpool_tevent *wrap_tp = NULL;
-	struct smbd_impersonate_tp_root_state *state = NULL;
-	size_t max_threads;
-
-	max_threads = pthreadpool_tevent_max_threads(main_tp);
-	SMB_ASSERT(max_threads > 0);
-
-	wrap_tp = pthreadpool_tevent_wrapper_create(main_tp,
-				mem_ctx,
-				&smbd_impersonate_tp_root_ops,
-				&state,
-				struct smbd_impersonate_tp_root_state);
-	if (wrap_tp == NULL) {
-		return NULL;
-	}
-
-	state->fallback_token = copy_unix_token(state, fallback_token);
-	if (state->fallback_token == NULL) {
-		int saved_errno = errno;
-		TALLOC_FREE(wrap_tp);
-		errno = saved_errno;
-		return NULL;
-	}
-
-	return wrap_tp;
-}
-
-static struct smb_vfs_ev_glue *smbd_impersonate_user_ev_glue_create(
-				struct connection_struct *conn,
-				uint64_t vuid,
-				struct auth_session_info *session_info)
-{
-	TALLOC_CTX *frame = talloc_stackframe();
-	struct smb_vfs_ev_glue *user_vfs_evg = NULL;
-	struct tevent_context *user_ev_ctx = NULL;
-	struct pthreadpool_tevent *user_tp_fd_safe = NULL;
-	struct pthreadpool_tevent *user_tp_path_safe = NULL;
-	bool user_tp_path_sync = true;
-	struct pthreadpool_tevent *user_tp_chdir_safe = NULL;
-	bool user_tp_chdir_sync = true;
-	struct pthreadpool_tevent *root_tp_fd_safe = NULL;
-	struct pthreadpool_tevent *root_tp_path_safe = NULL;
-	bool root_tp_path_sync = true;
-	struct pthreadpool_tevent *root_tp_chdir_safe = NULL;
-	bool root_tp_chdir_sync = true;
-	size_t max_threads;
-
-	if (vuid == UID_FIELD_INVALID) {
-		user_ev_ctx = smbd_impersonate_conn_sess_create(
-			conn->sconn->raw_ev_ctx, conn, session_info);
-		if (user_ev_ctx == NULL) {
-			TALLOC_FREE(frame);
-			return NULL;
-		}
-	} else {
-		user_ev_ctx = smbd_impersonate_conn_vuid_create(
-			conn->sconn->raw_ev_ctx, conn, vuid);
-		if (user_ev_ctx == NULL) {
-			TALLOC_FREE(frame);
-			return NULL;
-		}
-	}
-	SMB_ASSERT(talloc_reparent(conn, frame, user_ev_ctx));
-
-#ifdef HAVE_LINUX_THREAD_CREDENTIALS
-	user_tp_path_sync = lp_parm_bool(SNUM(conn),
-					 "smbd",
-					 "force sync user path safe threadpool",
-					 false);
-	user_tp_chdir_sync = lp_parm_bool(SNUM(conn),
-					  "smbd",
-					  "force sync user chdir safe threadpool",
-					  false);
-	root_tp_path_sync = lp_parm_bool(SNUM(conn),
-					 "smbd",
-					 "force sync root path safe threadpool",
-					 false);
-	root_tp_chdir_sync = lp_parm_bool(SNUM(conn),
-					  "smbd",
-					  "force sync root chdir safe threadpool",
-					  false);
-#endif
-
-	max_threads = pthreadpool_tevent_max_threads(conn->sconn->raw_thread_pool);
-	if (max_threads == 0) {
-		/*
-		 * We don't have real threads, so we need to force
-		 * the sync versions...
-		 */
-		user_tp_path_sync = true;
-		user_tp_chdir_sync = true;
-		root_tp_path_sync = true;
-		root_tp_chdir_sync = true;
-	}
-
-	/*
-	 * fd_safe is easy :-)
-	 */
-	user_tp_fd_safe = conn->sconn->raw_thread_pool;
-	root_tp_fd_safe = conn->sconn->raw_thread_pool;
-
-	if (user_tp_path_sync) {
-		/*
-		 * We don't have support for per thread credentials,
-		 * so we just provide a sync thread pool with a wrapper
-		 * that asserts that we are already in the required
-		 * impersonation state.
-		 */
-		user_tp_path_safe = smbd_impersonate_tp_current_create(conn,
-						conn->sconn->sync_thread_pool,
-						conn,
-						vuid,
-						false, /* chdir_safe */
-						session_info->unix_token);
-		if (user_tp_path_safe == NULL) {
-			TALLOC_FREE(frame);
-			return NULL;
-		}
-	} else {
-		user_tp_path_safe = smbd_impersonate_tp_sess_create(conn,
-						conn->sconn->raw_thread_pool,
-						session_info);
-		if (user_tp_path_safe == NULL) {
-			TALLOC_FREE(frame);
-			return NULL;
-		}
-	}
-	SMB_ASSERT(talloc_reparent(conn, frame, user_tp_path_safe));
-
-	if (pthreadpool_tevent_per_thread_cwd(user_tp_path_safe)) {
-		user_tp_chdir_safe = user_tp_path_safe;
-	} else {
-		user_tp_chdir_sync = true;
-	}
-
-	if (user_tp_chdir_sync) {
-		/*
-		 * We don't have support for per thread credentials,
-		 * so we just provide a sync thread pool with a wrapper
-		 * that asserts that we are already in the required
-		 * impersonation state.
-		 *
-		 * And it needs to cleanup after [f]chdir() within
-		 * the job...
-		 */
-		user_tp_chdir_safe = smbd_impersonate_tp_current_create(conn,
-						conn->sconn->sync_thread_pool,
-						conn,
-						vuid,
-						true, /* chdir_safe */
-						session_info->unix_token);
-		if (user_tp_chdir_safe == NULL) {
-			TALLOC_FREE(frame);
-			return NULL;
-		}
-		SMB_ASSERT(talloc_reparent(conn, frame, user_tp_chdir_safe));
-	} else {
-		SMB_ASSERT(user_tp_chdir_safe != NULL);
-	}
-
-	if (root_tp_path_sync) {
-		/*
-		 * We don't have support for per thread credentials,
-		 * so we just provide a sync thread pool with a wrapper
-		 * that wrapps the job in become_root()/unbecome_root().
-		 */
-		root_tp_path_safe = smbd_impersonate_tp_become_create(conn,
-						conn->sconn->sync_thread_pool,
-						false, /* chdir_safe */
-						become_root,
-						unbecome_root);
-		if (root_tp_path_safe == NULL) {
-			TALLOC_FREE(frame);
-			return NULL;
-		}
-	} else {
-		root_tp_path_safe = smbd_impersonate_tp_root_create(conn,
-						conn->sconn->raw_thread_pool,
-						SNUM(conn),
-						session_info->unix_token);
-		if (root_tp_path_safe == NULL) {
-			TALLOC_FREE(frame);
-			return NULL;
-		}
-	}
-	SMB_ASSERT(talloc_reparent(conn, frame, root_tp_path_safe));
-
-	if (pthreadpool_tevent_per_thread_cwd(root_tp_path_safe)) {
-		root_tp_chdir_safe = root_tp_path_safe;
-	} else {
-		root_tp_chdir_sync = true;
-	}
-
-	if (root_tp_chdir_sync) {
-		/*
-		 * We don't have support for per thread credentials,
-		 * so we just provide a sync thread pool with a wrapper
-		 * that wrapps the job in become_root()/unbecome_root().
-		 *
-		 * And it needs to cleanup after [f]chdir() within
-		 * the job...
-		 */
-		root_tp_chdir_safe = smbd_impersonate_tp_become_create(conn,
-						conn->sconn->sync_thread_pool,
-						true, /* chdir_safe */
-						become_root,
-						unbecome_root);
-		if (root_tp_chdir_safe == NULL) {
-			TALLOC_FREE(frame);
-			return NULL;
-		}
-		SMB_ASSERT(talloc_reparent(conn, frame, root_tp_chdir_safe));
-	} else {
-		SMB_ASSERT(root_tp_chdir_safe != NULL);
-	}
-
-	user_vfs_evg = smb_vfs_ev_glue_create(conn,
-					      user_ev_ctx,
-					      user_tp_fd_safe,
-					      user_tp_path_safe,
-					      user_tp_chdir_safe,
-					      conn->sconn->root_ev_ctx,
-					      root_tp_fd_safe,
-					      root_tp_path_safe,
-					      root_tp_chdir_safe);
-	if (user_vfs_evg == NULL) {
-		TALLOC_FREE(frame);
-		return NULL;
-	}
-
-	/*
-	 * Make sure everything is a talloc child of user_vfs_evg
-	 */
-	SMB_ASSERT(talloc_reparent(frame, user_vfs_evg, user_ev_ctx));
-	SMB_ASSERT(talloc_reparent(frame, user_vfs_evg, user_tp_path_safe));
-	if (user_tp_path_safe != user_tp_chdir_safe) {
-		SMB_ASSERT(talloc_reparent(frame, user_vfs_evg, user_tp_chdir_safe));
-	}
-	SMB_ASSERT(talloc_reparent(frame, user_vfs_evg, root_tp_path_safe));
-	if (root_tp_path_safe != root_tp_chdir_safe) {
-		SMB_ASSERT(talloc_reparent(frame, user_vfs_evg, root_tp_chdir_safe));
-	}
-
-	TALLOC_FREE(frame);
-	return user_vfs_evg;
-}
-- 
2.17.1


From 248096af811c3b5670435a80fe61069834e13bd9 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 28 Dec 2018 13:08:14 +0100
Subject: [PATCH 14/66] Revert "s3: vfs: add smb_vfs_ev_glue"

This reverts commit 1251a536df4b1df58d9ddacab03d3ebe6f4e5b60.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/include/vfs.h |  30 --
 source3/smbd/vfs.c    | 832 ------------------------------------------
 2 files changed, 862 deletions(-)

diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 6516869b24e2..959dd4059151 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -257,8 +257,6 @@
 /* Version 39 - Remove struct dfree_cached_info pointer from
 		connection struct */
 /* Bump to version 40, Samba 4.10 will ship with that */
-/* Version 40 - Introduce smb_vfs_ev_glue infrastructure. */
-/* Version 40 - Add vfs_not_implemented_* helper functions. */
 /* Version 40 - Add SMB_VFS_GETXATTRAT_SEND/RECV */
 /* Version 40 - Add SMB_VFS_GET_DOS_ATTRIBUTES_SEND/RECV */
 
@@ -283,9 +281,6 @@ struct smb_file_time;
 struct blocking_lock_record;
 struct smb_filename;
 struct dfs_GetDFSReferral;
-struct tevent_context;
-struct pthreadpool_tevent;
-struct smb_vfs_ev_glue;
 
 typedef union unid_t {
 	uid_t uid;
@@ -1553,31 +1548,6 @@ void *vfs_fetch_fsp_extension(vfs_handle_struct *handle, files_struct *fsp);
 void smb_vfs_assert_all_fns(const struct vfs_fn_pointers* fns,
 			    const char *module);
 
-/*
- * Notice the "Design of the smb_vfs_ev_glue infrastructure"
- * comment in source3/smbd/vfs.c!
- *
- * This explains smb_vfs_ev_glue infrastructure in detail.
- */
-struct tevent_context *smb_vfs_ev_glue_ev_ctx(const struct smb_vfs_ev_glue *evg);
-struct pthreadpool_tevent *smb_vfs_ev_glue_tp_fd_safe(const struct smb_vfs_ev_glue *evg);
-struct pthreadpool_tevent *smb_vfs_ev_glue_tp_path_safe(const struct smb_vfs_ev_glue *evg);
-struct pthreadpool_tevent *smb_vfs_ev_glue_tp_chdir_safe(const struct smb_vfs_ev_glue *evg);
-const struct smb_vfs_ev_glue *smb_vfs_ev_glue_get_root_glue(const struct smb_vfs_ev_glue *evg);
-struct smb_vfs_ev_glue *smb_vfs_ev_glue_create(TALLOC_CTX *mem_ctx,
-				struct tevent_context *user_ev,
-				struct pthreadpool_tevent *user_tp_fd_safe,
-				struct pthreadpool_tevent *user_tp_path_safe,
-				struct pthreadpool_tevent *user_tp_chdir_safe,
-				struct tevent_context *root_ev,
-				struct pthreadpool_tevent *root_tp_fd_safe,
-				struct pthreadpool_tevent *root_tp_path_safe,
-				struct pthreadpool_tevent *root_tp_chdir_safe);
-struct smb_vfs_ev_glue *smb_vfs_ev_glue_create_switch(
-			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *return_evg,
-			const struct smb_vfs_ev_glue *run_evg);
-
 /*
  * Helper functions from source3/modules/vfs_not_implemented.c
  */
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index 0cf8f8caa1d5..5e0ca091f7b0 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -1452,838 +1452,6 @@ struct file_id vfs_file_id_from_sbuf(connection_struct *conn, const SMB_STRUCT_S
 	return SMB_VFS_FILE_ID_CREATE(conn, sbuf);
 }
 
-/*
- * Design of the smb_vfs_ev_glue infrastructure:
- *
- * smb_vfs_ev_glue makes it possible to pass
- * down an tevent_context and pthreadpool_tevent
- * used for impersonation through the SMB_VFS stack.
- *
- * tevent_req based function take an tevent_context as
- * there 2nd argument, e.g.:
- *
- *   struct tevent_req *something_send(TALLOC_CTX *mem_ctx,
- *                                     struct tevent_context *ev,
- *                                     ...);
- *
- * For the SMB_VFS stack we'll use the following:
- *
- *   struct tevent_req *SMB_VFS_SOMETHING_SEND(TALLOC_CTX *mem_ctx,
- *                                             const struct smb_vfs_ev_glue *evg,
- *                                             ...);
- *
- * Typically the 'evg' is just passed through the stack down
- * to vfs_default.c. In order to do real work an
- * tevent_context and pthreadpool_tevent are required
- * to do call a 'somthing()' syscall in an async fashion.
- * Therefore it will the following to get the pointer
- * back out of evg:
- *
- *   ev = smb_vfs_ev_glue_ev_ctx(evg);
- *   tp = smb_vfs_ev_glue_tp_chdir_safe(evg);
- *
- * If some function in the stack is sure it needs to run as root
- * to get some information (after careful checks!), it used
- * to frame that work into become_root()/unbecome_root().
- * This can't work when using async functions!
- * Now it's possible to use something like this (simplified!):
- *
- *   ev = smb_vfs_ev_glue_ev_ctx(evg);
- *   root_evg = smb_vfs_ev_glue_get_root_glue(evg);
- *   subreq = SMB_VFS_SOMETHING_NEXT_SEND(state, root_evg, ...);
- *   if (tevent_req_nomem(subreq, req)) {
- *        return tevent_req_post(req, ev);
- *   }
- *   tevent_req_set_callback(subreq, module_something_done, req);
- *
- *   return req;
- *
- *   static void module_something_done(struct tevent_req *subreq)
- *   {
- *      ...
- *
- *      status = SMB_VFS_SOMETHING_NEXT_RECV(subreq, &state->aio_state);
- *      TALLOC_FREE(subreq);
- *
- *      tevent_req_done(req);
- *   }
- *
- * In the code above the something_send_fn() function of the next
- * module in the stack will be called as root.
- * The smb_vfs_call_something_*() glue code, which is the magic
- * behind the SMB_VFS_SOMETHING[_NEXT]_{SEND,RECV}() macros,
- * will look like this:
- *
- *   struct smb_vfs_call_something_state {
- *       ssize_t (*recv_fn)(struct tevent_req *req,
- *                          struct vfs_aio_state *aio_state,
- *                          ...);
- *       ssize_t retval;
- *       struct vfs_aio_state vfs_aio_state;
- *       ...
- *   };
- *
- *   static void smb_vfs_call_something_done(struct tevent_req *subreq);
- *
- *   struct tevent_req *smb_vfs_call_something_send(
- *                  TALLOC_CTX *mem_ctx,
- *                  const struct smb_vfs_ev_glue *evg,
- *                  struct vfs_handle_struct *handle,
- *                  ...)
- *   {
- *       struct tevent_req *req = NULL;
- *       struct smb_vfs_call_something_state *state = NULL;
- *       struct tevent_req *subreq = NULL;
- *       bool ok;
- *
- *       req = tevent_req_create(mem_ctx, &state,
- *                               struct smb_vfs_call_something_state);
- *       if (req == NULL) {
- *           return NULL;
- *       }
- *
- *       VFS_FIND(something_send);
- *       state->recv_fn = handle->fns->something_recv_fn;
- *
- *       ok = smb_vfs_ev_glue_push_use(evg, req);
- *       if (!ok) {
- *           tevent_req_error(req, EIO);
- *           return tevent_req_post(req, evg->return_ev);
- *       }
- *
- *       subreq = handle->fns->something_send_fn(mem_ctx,
- *                                               evg->next_glue,
- *                                               handle,
- *                                               ...);
- *       smb_vfs_ev_glue_pop_use(evg);
- *
- *       if (tevent_req_nomem(subreq, req)) {
- *           return tevent_req_post(req, evg->return_ev);
- *       }
- *       tevent_req_set_callback(subreq, smb_vfs_call_something_done, req);
- *
- *       return req;
- *   }
- *
- *   static void smb_vfs_call_something_done(struct tevent_req *subreq)
- *   {
- *       struct tevent_req *req =
- *           tevent_req_callback_data(subreq,
- *           struct tevent_req);
- *       struct smb_vfs_call_something_state *state =
- *           tevent_req_data(req,
- *           struct smb_vfs_call_something_state);
- *
- *       state->retval = state->recv_fn(subreq,
- *                                      &state->vfs_aio_state,
- *                                      ....);
- *       TALLOC_FREE(subreq);
- *
- *       if (state->retval == -1) {
- *           tevent_req_error(req, state->vfs_aio_state.error);
- *           return;
- *       }
- *       tevent_req_done(req);
- *   }
- *
- *   ssize_t smb_vfs_call_something_recv(struct tevent_req *req,
- *                                        struct vfs_aio_state *aio_state,
- *                                        ....)
- *   {
- *       struct smb_vfs_call_something_state *state =
- *           tevent_req_data(req,
- *           struct smb_vfs_call_something_state);
- *       ssize_t retval = state->retval;
- *
- *       if (tevent_req_is_unix_error(req, &aio_state->error)) {
- *           tevent_req_received(req);
- *           return -1;
- *       }
- *
- *       *aio_state = state->vfs_aio_state;
- *       ...
- *
- *       tevent_req_received(req);
- *       return retval;
- *   }
- *
- * The most important details are these:
- *
- * 1. smb_vfs_ev_glue_push_use(evg, req):
- *    - is a no-op if evg->run_ev and evg->return_ev are the same,
- *      it means that we're already at the correct impersonation
- *      and don't need any additional work to be done.
- *    - Otherwise it will call tevent_req_defer_callback(req, evg->return_ev)
- *      This means that tevent_req_error() and tevent_req_done()
- *      will just trigger an immediate event on evg->return_ev.
- *      Therefore the callers callback function will be called
- *      in the impersonation of evg->return_ev! This is important
- *      in order to get the impersonation correct on the way back
- *      through the stack.
- *    - It will call tevent_context_push_use(evg->run_ev),
- *      which will start the impersonation to run_ev.
- *      So the following code run in the correct context.
- * 2. handle->fns->something_send_fn(..., evg->next_glue, ...):
- *    - We're passing evg->next_glue to the next module.
- *    - Typically evg->next_glue points to evg again.
- *    - In case evg->run_ev and evg->return_ev are not the same,
- *      next_glue will have run_ev and return_ev pointing to evg->run_ev.
- *      So that the switch from evg->run_ev to evg->return_ev
- *      happens on the correct boundary.
- * 3. smb_vfs_ev_glue_pop_use(evg):
- *    - is a no-op if evg->run_ev and evg->return_ev are the same,
- *      it means that we're already at the correct impersonation
- *      and don't need any additional work to be done.
- *    - It will call tevent_context_pop_use(evg->run_ev),
- *      which will revert the impersonation done in
- *      smb_vfs_ev_glue_push_use().
- * 4. smb_vfs_call_something_send():
- *    - The is called in the environment of evg->return_ev.
- *    - So it needs to use tevent_req_post(req, evg->return_ev)
- * 5. smb_vfs_call_something_done():
- *    - The is called in the environment of evg->run_ev
- * 6. smb_vfs_call_something_recv():
- *    - The is called in the environment of evg->return_ev again.
- *
- *
- * Here are some more complex examples:
- *
- * Example 1: only user_evg without switch to root
- *
- * SMBD: already impersonated user_evg
- *  evg'1 = smb2_req->user_evg
- *  r'1 = SMB_VFS_*_SEND(evg'1); # smb_vfs_call_*_send()
- *  |
- *  | smb_vfs_ev_glue_push_use(evg'1, r'1);
- *  | |
- *  | | # no-op run_ev == return_ev
- *  | |
- *  | evg'2 = evg'1->next_glue;
- *  | r'2 = module1_*_send(evg'2);
- *  | |
- *  | | evg'3 = evg'2
- *  | | r'3 = SMB_VFS_*_NEXT_SEND(evg'3); # smb_vfs_call_*_send()
- *  | | |
- *  | | | smb_vfs_ev_glue_push_use(evg'3, r'3);
- *  | | | |
- *  | | | | # no-op run_ev == return_ev
- *  | | | |
- *  | | | evg'4 = evg'3->next_glue;
- *  | | | r'4 = module2_*_send(evg'4);
- *  | | | |
- *  | | | | evg'5 = evg'4
- *  | | | | r'5 = SMB_VFS_*_NEXT_SEND(evg'5); # smb_vfs_call_*_send()
- *  | | | | |
- *  | | | | | smb_vfs_ev_glue_push_use(evg'5, r'5);
- *  | | | | | |
- *  | | | | | | # no-op run_ev == return_ev
- *  | | | | | |
- *  | | | | | evg'6 = evg'5->next_glue;
- *  | | | | | r'6 = default_*_send(evg'6);
- *  | | | | | |
- *  | | | | | | ev'6 = smb_vfs_ev_glue_ev_ctx(evg'6)
- *  | | | | | | tp'6 = smb_vfs_ev_glue_tp_chdir_safe(evg'6)
- *  | | | | | | r'7 = pthreadpool_tevent_send(ev'6, tp'6);
- *  | | | | | | |
- *  | | | | | | | pthread_create...
- *  | | | | | | |
- *  | | | | | | tevent_req_set_callback(r'7, default_*_done, r'6);
- *  | | | | | |
- *  | | | | | smb_vfs_ev_glue_pop_use(evg'5);
- *  | | | | | |
- *  | | | | | | # no-op run_ev == return_ev
- *  | | | | | |
- *  | | | | | tevent_req_set_callback(r'6, smb_vfs_call_*_done, r'5);
- *  | | | | |
- *  | | | | tevent_req_set_callback(r'5, module2_*_done, r'4);
- *  | | | |
- *  | | | smb_vfs_ev_glue_pop_use(evg'3);
- *  | | | |
- *  | | | | # no-op run_ev == return_ev
- *  | | | |
- *  | | | tevent_req_set_callback(r'4, smb_vfs_call_*_done, r'3);
- *  | | |
- *  | | tevent_req_set_callback(r'3, module1_*_done, r'2);
- *  | |
- *  | smb_vfs_ev_glue_pop_use(evg'1);
- *  | |
- *  | | # no-op run_ev == return_ev
- *  | |
- *  | tevent_req_set_callback(r'2, smb_vfs_call_*_done, r'1);
- *  |
- *  tevent_req_set_callback(r'1, smbd_*_done, smb2_req);
- *
- *  Worker thread finished, just one event handler processes
- *  everything as there's no impersonation change.
- *
- *  tevent_common_invoke_immediate_handler:
- *  |
- *  | before_immediate_handler(ev'6);
- *  | |
- *  | | change_to_user()
- *  | |
- *  | pthreadpool_tevent_job_done(r'7);
- *  | |
- *  | | default_*_done(r'7);
- *  | | |
- *  | | | pthreadpool_tevent_recv(r'7);
- *  | | | TALLOC_FREE(r'7);
- *  | | | tevent_req_done('r6);
- *  | | | |
- *  | | | | smb_vfs_call_*_done(r'6);
- *  | | | | |
- *  | | | | | default_*_recv(r'6);
- *  | | | | | TALLOC_FREE(r'6)
- *  | | | | | tevent_req_done(r'5);
- *  | | | | | |
- *  | | | | | | module2_*_done(r'5):
- *  | | | | | | |
- *  | | | | | | | SMB_VFS_*_recv(r'5); # smb_vfs_call_*_recv()
- *  | | | | | | | TALLOC_FREE(r'5)
- *  | | | | | | | tevent_req_done(r'4);
- *  | | | | | | | |
- *  | | | | | | | | smb_vfs_call_*_done(r'4);
- *  | | | | | | | | |
- *  | | | | | | | | | module2_*_recv(r'4);
- *  | | | | | | | | | TALLOC_FREE(r'4)
- *  | | | | | | | | | tevent_req_done(r'3);
- *  | | | | | | | | | |
- *  | | | | | | | | | | module1_*_done(r'3):
- *  | | | | | | | | | | |
- *  | | | | | | | | | | | SMB_VFS_*_recv(r'3); # smb_vfs_call_*_recv()
- *  | | | | | | | | | | | TALLOC_FREE(r'3)
- *  | | | | | | | | | | | tevent_req_done(r'2);
- *  | | | | | | | | | | | |
- *  | | | | | | | | | | | | smb_vfs_*_done(r'2);
- *  | | | | | | | | | | | | |
- *  | | | | | | | | | | | | | module1_*_recv(r'2);
- *  | | | | | | | | | | | | | TALLOC_FREE(r'2)
- *  | | | | | | | | | | | | | tevent_req_done(r'1);
- *  | | | | | | | | | | | | | |
- *  | | | | | | | | | | | | | | smbd_*_done(r'1);
- *  | | | | | | | | | | | | | | |
- *  | | | | | | | | | | | | | | | SMB_VFS_*_recv(r'1); # smb_vfs_call_*_recv()
- *  | | | | | | | | | | | | | | | TALLOC_FREE(r'1)
- *  | | | | | | | | | | | | | | | smbd_response_to_client()
- *  | | | | | | | | | | | | | | | return
- *  | | | | | | | | | | | | | | |
- *  | | | | | | | | | | | | | | return
- *  | | | | | | | | | | | | | |
- *  | | | | | | | | | | | | | return
- *  | | | | | | | | | | | | |
- *  | | | | | | | | | | | | return
- *  | | | | | | | | | | | |
- *  | | | | | | | | | | | return
- *  | | | | | | | | | | |
- *  | | | | | | | | | | return
- *  | | | | | | | | | |
- *  | | | | | | | | | return
- *  | | | | | | | | |
- *  | | | | | | | | return
- *  | | | | | | | |
- *  | | | | | | | return
- *  | | | | | | |
- *  | | | | | | return
- *  | | | | | |
- *  | | | | | return
- *  | | | | |
- *  | | | | return
- *  | | | |
- *  | | | return
- *  | | |
- *  | | return
- *  | |
- *  | after_immediate_handler(ev'6);
- *  | |
- *  | | # lazy no change_to_user()
- *  | |
- *  | return
- *
- *
- * Example 2: start with user_evg and let module1 switch to root
- *
- * SMBD: already impersonated user_evg
- *  evg'1 = smb2_req->user_evg
- *  r'1 = SMB_VFS_*_SEND(evg'1); # smb_vfs_call_*_send()
- *  |
- *  | smb_vfs_ev_glue_push_use(evg'1, r'1);
- *  | |
- *  | | # no-op run_ev == return_ev
- *  | |
- *  | evg'2 = evg'1->next_glue;
- *  | r'2 = module1_*_send(evg'2);
- *  | |
- *  | | evg'3 = smb_vfs_ev_glue_get_root_glue(evg'2)
- *  | | r'3 = SMB_VFS_*_NEXT_SEND(evg'3); # smb_vfs_call_*_send()
- *  | | |
- *  | | | smb_vfs_ev_glue_push_use(evg'3, r'3);
- *  | | | |
- *  | | | | tevent_req_defer_callback(r'3, evg'3->return_ev);
- *  | | | | tevent_context_push_use(evg'3->run_ev)
- *  | | | | |
- *  | | | | | become_root()
- *  | | | | |
- *  | | | |
- *  | | | evg'4 = evg'3->next_glue;
- *  | | | r'4 = module2_*_send(evg'4);
- *  | | | |
- *  | | | | evg'5 = smb_vfs_ev_glue_get_root_glue(evg'4)
- *  | | | | r'5 = SMB_VFS_*_NEXT_SEND(evg'5); # smb_vfs_call_*_send()
- *  | | | | |
- *  | | | | | smb_vfs_ev_glue_push_use(evg'5, r'5);
- *  | | | | | |
- *  | | | | | | # no-op run_ev == return_ev, already root
- *  | | | | | |
- *  | | | | | evg'6 = evg'5->next_glue;
- *  | | | | | r'6 = default_*_send(evg'6);
- *  | | | | | |
- *  | | | | | | ev'6 = smb_vfs_ev_glue_ev_ctx(evg'6)
- *  | | | | | | tp'6 = smb_vfs_ev_glue_tp_chdir_safe(evg'6)
- *  | | | | | | r'7 = pthreadpool_tevent_send(ev'6, tp'6);
- *  | | | | | | |
- *  | | | | | | | pthread_create...
- *  | | | | | | |
- *  | | | | | | tevent_req_set_callback(r'7, default_*_done, r'6);
- *  | | | | | |
- *  | | | | | smb_vfs_ev_glue_pop_use(evg'5);
- *  | | | | | |
- *  | | | | | | # no-op run_ev == return_ev, still stay as root
- *  | | | | | |
- *  | | | | | tevent_req_set_callback(r'6, smb_vfs_*_done, r'5);
- *  | | | | |
- *  | | | | tevent_req_set_callback(r'5, module2_*_done, r'4);
- *  | | | |
- *  | | | smb_vfs_ev_glue_pop_use(evg'3);
- *  | | | |
- *  | | | | tevent_context_pop_use(evg'3->run_ev)
- *  | | | | |
- *  | | | | | unbecome_root()
- *  | | | |
- *  | | | tevent_req_set_callback(r'4, smb_vfs_*_done, r'3);
- *  | | |
- *  | | tevent_req_set_callback(r'3, module1_*_done, r'2);
- *  | |
- *  | smb_vfs_ev_glue_pop_use(evg'1);
- *  | |
- *  | | # no-op run_ev == return_ev
- *  | |
- *  | tevent_req_set_callback(r'2, smb_vfs_*_done, r'1);
- *  |
- *  tevent_req_set_callback(r'1, smbd_*_done, smb2_req);
- *
- *  Worker thread finished, just one event handler processes
- *  everything as there's no impersonation change.
- *
- *  tevent_common_invoke_immediate_handler:
- *  |
- *  | before_immediate_handler(ev'6);
- *  | |
- *  | | become_root()
- *  | |
- *  | pthreadpool_tevent_job_done(r'7);
- *  | |
- *  | | default_*_done(r'7);
- *  | | |
- *  | | | pthreadpool_tevent_recv(r'7);
- *  | | | TALLOC_FREE(r'7);
- *  | | | tevent_req_done('r6);
- *  | | | |
- *  | | | | smb_vfs_*_done(r'6);
- *  | | | | |
- *  | | | | | default_*_recv(r'6);
- *  | | | | | TALLOC_FREE(r'6)
- *  | | | | | tevent_req_done(r'5);
- *  | | | | | |
- *  | | | | | | module2_*_done(r'5):
- *  | | | | | | |
- *  | | | | | | | SMB_VFS_*_recv(r'5);
- *  | | | | | | | TALLOC_FREE(r'5)
- *  | | | | | | | tevent_req_done(r'4);
- *  | | | | | | | |
- *  | | | | | | | | smb_vfs_*_done(r'4);
- *  | | | | | | | | |
- *  | | | | | | | | | module2_*_recv(r'4);
- *  | | | | | | | | | TALLOC_FREE(r'4)
- *  | | | | | | | | | tevent_req_done(r'3);
- *  | | | | | | | | | | return
- *  | | | | | | | | | |
- *  | | | | | | | | | return
- *  | | | | | | | | |
- *  | | | | | | | | return
- *  | | | | | | | |
- *  | | | | | | | return
- *  | | | | | | |
- *  | | | | | | return
- *  | | | | | |
- *  | | | | | return
- *  | | | | |
- *  | | | | return
- *  | | | |
- *  | | | return
- *  | | |
- *  | | return
- *  | |
- *  | |
- *  | after_immediate_handler(ev'6);
- *  | |
- *  | | unbecome_root()
- *  | |
- *  | return
- *  |
- *  tevent_common_invoke_immediate_handler:
- *  |
- *  | before_immediate_handler(ev'6);
- *  | |
- *  | | change_to_user()
- *  | |
- *  | tevent_req_trigger();
- *  | ...
- *  | _tevent_req_notify_callback(r'3)
- *  | |
- *  | | module1_*_done(r'3):
- *  | | |
- *  | | | SMB_VFS_*_recv(r'3);
- *  | | | TALLOC_FREE(r'3)
- *  | | | tevent_req_done(r'2);
- *  | | | |
- *  | | | | smb_vfs_*_done(r'2);
- *  | | | | |
- *  | | | | | module1_*_recv(r'2);
- *  | | | | | TALLOC_FREE(r'2)
- *  | | | | | tevent_req_done(r'1);
- *  | | | | | |
- *  | | | | | | smbd_*_done(r'1);
- *  | | | | | | |
- *  | | | | | | | SMB_VFS_*_recv(r'1);
- *  | | | | | | | TALLOC_FREE(r'1)
- *  | | | | | | | smbd_response_to_client()
- *  | | | | | | | return
- *  | | | | | | |
- *  | | | | | | return
- *  | | | | | |
- *  | | | | | return
- *  | | | | |
- *  | | | | return
- *  | | | |
- *  | | | return
- *  | | |
- *  | | return
- *  | |
- *  | after_immediate_handler(ev'6);
- *  | |
- *  | | # lazy no change_to_user()
- *  | |
- *  | return
- *
- */
-struct smb_vfs_ev_glue {
-	/*
-	 * The event context that should be used
-	 * to report the result back.
-	 *
-	 * The is basically the callers context.
-	 */
-	struct tevent_context *return_ev;
-
-	/*
-	 * The event context and threadpool wrappers
-	 * the current context should use.
-	 *
-	 * tp_fd_safe only allows fd based functions
-	 * which don't require impersonation, this
-	 * is basically the raw threadpool.
-	 *
-	 * tp_path_safe allows path based functions
-	 * to be called under the correct impersonation.
-	 * But chdir/fchdir is not allowed!
-	 * Typically calls like openat() or other *at()
-	 * syscalls.
-	 *
-	 * tp_chdir_safe is like path_safe, but also
-	 * allows chdir/fchdir to be called, the job
-	 * can safely return with a changed directory,
-	 * the threadpool wrapper takes care of
-	 * a cleanup if required.
-	 * This is needed if *at() syscalls need
-	 * to be simulated by fchdir();$syscall(),
-	 * e.g. getxattr().
-	 *
-	 * The distinction between these threadpool
-	 * is required because of OS limitations
-	 * (as of 2018):
-	 * - only Linux supports per thread
-	 *   credentials (seteuid....)
-	 * - only Linux supports a per thread
-	 *   current working directory,
-	 *   using unshare(CLONE_FS). But
-	 *   in some constrained container
-	 *   environments even that is not available
-	 *   on Linux.
-	 *
-	 * tp_fd_safe is typically the raw threadpool
-	 * without a wrapper.
-	 *
-	 * On Linux tp_path_safe and tp_chdir_safe
-	 * are typically the same (if unshare(CLONE_FS) is available)
-	 * they're implemented as wrappers of the raw threadpool.
-	 *
-	 * On other OSes tp_path_safe is a wrapper
-	 * arround a sync threadpool (without real threads, just blocking
-	 * the main thread), but hidden behind the pthreadpool_tevent
-	 * api in order to make the restriction transparent.
-	 *
-	 * On other OSes tp_chdir_safe is a wrapper
-	 * arround a sync threadpool (without real threads, just blocking
-	 * the main thread), but hidden behind the pthreadpool_tevent
-	 * api in order to make the restriction transparent.
-	 * It just remembers/restores the current working directory,
-	 * typically using open(".", O_RDONLY | O_DIRECTORY) and fchdir().
-	 */
-	struct tevent_context *run_ev;
-	struct pthreadpool_tevent *run_tp_fd_safe;
-	struct pthreadpool_tevent *run_tp_path_safe;
-	struct pthreadpool_tevent *run_tp_chdir_safe;
-
-	/*
-	 * The glue that should be passed down
-	 * to sub request in the stack.
-	 *
-	 * Typically this points to itself.
-	 *
-	 * But smb_vfs_ev_glue_create_switch() allows
-	 * to create context that can switch
-	 * between two user glues.
-	 */
-	const struct smb_vfs_ev_glue *next_glue;
-
-	/*
-	 * If some code path wants to run
-	 * some constraint code as root,
-	 * basically an async version of become_root()
-	 * and unbecome_root().
-	 *
-	 * The caller can call smb_vfs_ev_glue_get_root_glue()
-	 * to get a root glue that can be passed
-	 * to the SMB_VFS_*_SEND() function that
-	 * should run as root.
-	 *
-	 * Note that the callback (registered with
-	 * tevent_req_set_callback()) won't run as
-	 * root anymore!
-	 */
-	const struct smb_vfs_ev_glue *root_glue;
-};
-
-static struct smb_vfs_ev_glue *smb_vfs_ev_glue_create_internal(
-	TALLOC_CTX *mem_ctx,
-	struct tevent_context *return_ev,
-	struct tevent_context *run_ev,
-	struct pthreadpool_tevent *run_tp_fd_safe,
-	struct pthreadpool_tevent *run_tp_path_safe,
-	struct pthreadpool_tevent *run_tp_chdir_safe)
-{
-	struct smb_vfs_ev_glue *evg = NULL;
-
-	evg = talloc_zero(mem_ctx, struct smb_vfs_ev_glue);
-	if (evg == NULL) {
-		return NULL;
-	}
-	*evg = (struct smb_vfs_ev_glue) {
-		.return_ev = return_ev,
-		.run_ev = run_ev,
-		.run_tp_fd_safe = run_tp_fd_safe,
-		.run_tp_path_safe = run_tp_path_safe,
-		.run_tp_chdir_safe = run_tp_chdir_safe,
-		.next_glue = evg,
-	};
-
-	return evg;
-}
-
-struct tevent_context *smb_vfs_ev_glue_ev_ctx(const struct smb_vfs_ev_glue *evg)
-{
-	return evg->run_ev;
-}
-
-struct pthreadpool_tevent *smb_vfs_ev_glue_tp_fd_safe(const struct smb_vfs_ev_glue *evg)
-{
-	return evg->run_tp_fd_safe;
-}
-
-struct pthreadpool_tevent *smb_vfs_ev_glue_tp_path_safe(const struct smb_vfs_ev_glue *evg)
-{
-	return evg->run_tp_path_safe;
-}
-
-struct pthreadpool_tevent *smb_vfs_ev_glue_tp_chdir_safe(const struct smb_vfs_ev_glue *evg)
-{
-	return evg->run_tp_chdir_safe;
-}
-
-const struct smb_vfs_ev_glue *smb_vfs_ev_glue_get_root_glue(const struct smb_vfs_ev_glue *evg)
-{
-	return evg->root_glue;
-}
-
-struct smb_vfs_ev_glue *smb_vfs_ev_glue_create(TALLOC_CTX *mem_ctx,
-				struct tevent_context *user_ev,
-				struct pthreadpool_tevent *user_tp_fd_safe,
-				struct pthreadpool_tevent *user_tp_path_safe,
-				struct pthreadpool_tevent *user_tp_chdir_safe,
-				struct tevent_context *root_ev,
-				struct pthreadpool_tevent *root_tp_fd_safe,
-				struct pthreadpool_tevent *root_tp_path_safe,
-				struct pthreadpool_tevent *root_tp_chdir_safe)
-{
-	struct smb_vfs_ev_glue *evg_uu = NULL;
-	struct smb_vfs_ev_glue *evg_ru = NULL;
-	struct smb_vfs_ev_glue *evg_rr = NULL;
-
-	/*
-	 * The top level glue (directly returned from this function).
-	 *
-	 * It uses user_ev and user_tp_* only.
-	 */
-	evg_uu = smb_vfs_ev_glue_create_internal(mem_ctx,
-						 user_ev, /* return_ev */
-						 user_ev, /* run_ev */
-						 user_tp_fd_safe,
-						 user_tp_path_safe,
-						 user_tp_chdir_safe);
-	if (evg_uu == NULL) {
-		return NULL;
-	}
-
-	/*
-	 * The first root glue (returned by smb_vfs_ev_glue_get_root_glue()).
-	 *
-	 * It uses root_ev and root_tp, but user_ev as return ev,
-	 * which means that the caller's callback (registered with
-	 * tevent_req_set_callback()) will run as user_ev.
-	 */
-	evg_ru = smb_vfs_ev_glue_create_internal(evg_uu,
-						 user_ev, /* return_ev */
-						 root_ev, /* run_ev */
-						 root_tp_fd_safe,
-						 root_tp_path_safe,
-						 root_tp_chdir_safe);
-	if (evg_ru == NULL) {
-		TALLOC_FREE(evg_uu);
-		return NULL;
-	}
-
-	/*
-	 * The second root glue (returned by smb_vfs_ev_glue_get_root_glue() on
-	 * root glue itself. This means code can always call
-	 * smb_vfs_ev_glue_get_root_glue() and don't have to care if the
-	 * passed glue is already a root glue.
-	 *
-	 * This will then recursively point to its own root_glue pointer.
-	 *
-	 * It only uses root_ev and root_tp.
-	 */
-	evg_rr = smb_vfs_ev_glue_create_internal(evg_ru,
-						 root_ev, /* return_ev */
-						 root_ev, /* run_ev */
-						 root_tp_fd_safe,
-						 root_tp_path_safe,
-						 root_tp_chdir_safe);
-	if (evg_rr == NULL) {
-		TALLOC_FREE(evg_uu);
-		return NULL;
-	}
-
-	/*
-	 * We now setup the glue hierarchy.
-	 *
-	 * Search for "Design of the smb_vfs_ev_glue infrastructure" above
-	 * for a detailed description how the chain works.
-	 *
-	 * "Example 2: start with user_evg and let module1 switch to root"
-	 * explains it for the root_glue chaining.
-	 */
-	evg_rr->root_glue = evg_rr;
-	evg_ru->root_glue = evg_rr;
-	evg_uu->root_glue = evg_ru;
-
-	/*
-	 * As evg_ru is a boundary with
-	 * run_ev != return_ev, we need to
-	 * alter its next_glue.
-	 */
-	evg_ru->next_glue = evg_rr;
-
-	return evg_uu;
-}
-
-/*
- * This can be used to create a temporary glue
- * if you need to switch between two user contexts
- *
- * It's the caller's duty to make sure both
- * glues stay alive for the lifetime of the
- * created switch.
- */
-struct smb_vfs_ev_glue *smb_vfs_ev_glue_create_switch(
-			TALLOC_CTX *mem_ctx,
-			const struct smb_vfs_ev_glue *return_evg,
-			const struct smb_vfs_ev_glue *run_evg)
-{
-	const struct smb_vfs_ev_glue *run_root = run_evg->root_glue;
-	struct smb_vfs_ev_glue *evg_u = NULL;
-	struct smb_vfs_ev_glue *evg_r = NULL;
-
-	/*
-	 * Here we basically need to dup run_evg (and run_evg->root_glue)
-	 * and replace their return_ev with return_evg->return_ev.
-	 *
-	 * We need to put the new evgs in front of the chain...
-	 */
-	evg_u = smb_vfs_ev_glue_create_internal(mem_ctx,
-						return_evg->return_ev,
-						run_evg->run_ev,
-						run_evg->run_tp_fd_safe,
-						run_evg->run_tp_path_safe,
-						run_evg->run_tp_chdir_safe);
-	if (evg_u == NULL) {
-		return NULL;
-	}
-
-	evg_r = smb_vfs_ev_glue_create_internal(evg_u,
-						return_evg->return_ev,
-						run_root->run_ev,
-						run_root->run_tp_fd_safe,
-						run_root->run_tp_path_safe,
-						run_root->run_tp_chdir_safe);
-	if (evg_r == NULL) {
-		return NULL;
-	}
-
-	/*
-	 * evg_r is a boundary with run_ev != return_ev.
-	 * As run_root is also a boundary, we need to
-	 * use run_root->next_glue in order to get
-	 * a glue that stays as root.
-	 *
-	 * The same applies to the chaining of root
-	 * glues.
-	 */
-	evg_r->next_glue = run_root->next_glue;
-	evg_r->root_glue = run_root->root_glue;
-
-	/*
-	 * evg_r is a boundary with run_ev != return_ev.
-	 * But run_evg is typically not a boundary,
-	 * we use it directly as next_glue.
-	 *
-	 * And the root_glue is the one we constructed above.
-	 */
-	evg_u->next_glue = run_evg;
-	evg_u->root_glue = evg_r;
-
-	return evg_u;
-}
-
 int smb_vfs_call_connect(struct vfs_handle_struct *handle,
 			 const char *service, const char *user)
 {
-- 
2.17.1


From 955150bb84aa50319243f5f5c9dbca85a40abbb7 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:34:00 +0100
Subject: [PATCH 15/66] Revert "smbd: introduce sconn->sync_thread_pool"

This reverts commit 0c97226356f2ba5f01a58d361371055caf11e2a7.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/globals.h |  1 -
 source3/smbd/msdfs.c   | 12 ------------
 source3/smbd/process.c | 16 +---------------
 3 files changed, 1 insertion(+), 28 deletions(-)

diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 6ae571844178..b6dc27d47beb 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -943,7 +943,6 @@ struct smbd_server_connection {
 		} locks;
 	} smb2;
 
-	struct pthreadpool_tevent *sync_thread_pool;
 	struct pthreadpool_tevent *raw_thread_pool;
 
 	struct smbXsrv_client *client;
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index 9b0b2de27caa..5283edbecfcd 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -33,7 +33,6 @@
 #include "libcli/security/security.h"
 #include "librpc/gen_ndr/ndr_dfsblobs.h"
 #include "lib/tsocket/tsocket.h"
-#include "lib/pthreadpool/pthreadpool_tevent.h"
 
 /**********************************************************************
  Parse a DFS pathname of the form \hostname\service\reqpath
@@ -253,7 +252,6 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx,
 	const char *vfs_user;
 	struct smbd_server_connection *sconn;
 	const char *servicename = lp_const_servicename(snum);
-	int ret;
 
 	sconn = talloc_zero(ctx, struct smbd_server_connection);
 	if (sconn == NULL) {
@@ -277,16 +275,6 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx,
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	/*
-	 * We only provide sync threadpools.
-	 */
-	ret = pthreadpool_tevent_init(sconn, 0, &sconn->sync_thread_pool);
-	if (ret != 0) {
-		TALLOC_FREE(sconn);
-		return NT_STATUS_NO_MEMORY;
-	}
-	sconn->raw_thread_pool = sconn->sync_thread_pool;
-
 	sconn->msg_ctx = msg;
 
 	conn = conn_new(sconn);
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 35b5f4df385d..8e1fceab0aaf 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -3907,7 +3907,6 @@ void smbd_process(struct tevent_context *ev_ctx,
 	const char *locaddr = NULL;
 	const char *remaddr = NULL;
 	int ret;
-	size_t max_threads;
 	NTSTATUS status;
 	struct timeval tv = timeval_current();
 	NTTIME now = timeval_to_nttime(&tv);
@@ -3953,20 +3952,7 @@ void smbd_process(struct tevent_context *ev_ctx,
 	ret = pthreadpool_tevent_init(sconn, lp_aio_max_threads(),
 				      &sconn->raw_thread_pool);
 	if (ret != 0) {
-		exit_server("pthreadpool_tevent_init(raw) failed.");
-	}
-
-	max_threads = pthreadpool_tevent_max_threads(sconn->raw_thread_pool);
-	if (max_threads == 0) {
-		/*
-		 * We only have a sync pool, no need to create a 2nd one.
-		 */
-		sconn->sync_thread_pool = sconn->raw_thread_pool;
-	} else {
-		ret = pthreadpool_tevent_init(sconn, 0, &sconn->sync_thread_pool);
-		if (ret != 0) {
-			exit_server("pthreadpool_tevent_init(sync) failed.");
-		}
+		exit_server("pthreadpool_tevent_init() failed.");
 	}
 
 	if (lp_server_max_protocol() >= PROTOCOL_SMB2_02) {
-- 
2.17.1


From f061a62a75fb8ee1ead08d1221ef2c9dd75b9b29 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:34:20 +0100
Subject: [PATCH 16/66] smbd: rename sconn->raw_thread_pool to sconn->pool

This is basically a revert of commit
2be7518ae5a3c046f5fca04ecc83f9f7044eac74.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/modules/vfs_aio_pthread.c   | 2 +-
 source3/modules/vfs_default.c       | 9 ++++-----
 source3/smbd/globals.h              | 2 +-
 source3/smbd/process.c              | 2 +-
 source3/smbd/smb2_query_directory.c | 4 ++--
 5 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/source3/modules/vfs_aio_pthread.c b/source3/modules/vfs_aio_pthread.c
index da1ca534907f..c1d1a7d518a6 100644
--- a/source3/modules/vfs_aio_pthread.c
+++ b/source3/modules/vfs_aio_pthread.c
@@ -277,7 +277,7 @@ static int open_async(const files_struct *fsp,
 
 	subreq = pthreadpool_tevent_job_send(opd,
 					     fsp->conn->user_ev_ctx,
-					     fsp->conn->sconn->raw_thread_pool,
+					     fsp->conn->sconn->pool,
 					     aio_open_worker, opd);
 	if (subreq == NULL) {
 		return -1;
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 0a07d4069d75..1734361fca95 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -686,7 +686,7 @@ static struct tevent_req *vfswrap_pread_send(struct vfs_handle_struct *handle,
 	SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
 
 	subreq = pthreadpool_tevent_job_send(
-		state, ev, handle->conn->sconn->raw_thread_pool,
+		state, ev, handle->conn->sconn->pool,
 		vfs_pread_do, state);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
@@ -804,7 +804,7 @@ static struct tevent_req *vfswrap_pwrite_send(struct vfs_handle_struct *handle,
 	SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
 
 	subreq = pthreadpool_tevent_job_send(
-		state, ev, handle->conn->sconn->raw_thread_pool,
+		state, ev, handle->conn->sconn->pool,
 		vfs_pwrite_do, state);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
@@ -914,8 +914,7 @@ static struct tevent_req *vfswrap_fsync_send(struct vfs_handle_struct *handle,
 	SMBPROFILE_BYTES_ASYNC_SET_IDLE(state->profile_bytes);
 
 	subreq = pthreadpool_tevent_job_send(
-		state, ev, handle->conn->sconn->raw_thread_pool,
-		vfs_fsync_do, state);
+		state, ev, handle->conn->sconn->pool, vfs_fsync_do, state);
 	if (tevent_req_nomem(subreq, req)) {
 		return tevent_req_post(req, ev);
 	}
@@ -3037,7 +3036,7 @@ static struct tevent_req *vfswrap_getxattrat_send(
 	subreq = pthreadpool_tevent_job_send(
 			state,
 			ev,
-			dir_fsp->conn->sconn->raw_thread_pool,
+			dir_fsp->conn->sconn->pool,
 			vfswrap_getxattrat_do_async,
 			state);
 	if (tevent_req_nomem(subreq, req)) {
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index b6dc27d47beb..5695663cc665 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -943,7 +943,7 @@ struct smbd_server_connection {
 		} locks;
 	} smb2;
 
-	struct pthreadpool_tevent *raw_thread_pool;
+	struct pthreadpool_tevent *pool;
 
 	struct smbXsrv_client *client;
 };
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 8e1fceab0aaf..0a4106257f58 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -3950,7 +3950,7 @@ void smbd_process(struct tevent_context *ev_ctx,
 	sconn->msg_ctx = msg_ctx;
 
 	ret = pthreadpool_tevent_init(sconn, lp_aio_max_threads(),
-				      &sconn->raw_thread_pool);
+				      &sconn->pool);
 	if (ret != 0) {
 		exit_server("pthreadpool_tevent_init() failed.");
 	}
diff --git a/source3/smbd/smb2_query_directory.c b/source3/smbd/smb2_query_directory.c
index 1a3447c3a828..ab6c3dc788ee 100644
--- a/source3/smbd/smb2_query_directory.c
+++ b/source3/smbd/smb2_query_directory.c
@@ -515,7 +515,7 @@ static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx,
 	if (state->async_dosmode) {
 		size_t max_threads;
 
-		max_threads = pthreadpool_tevent_max_threads(conn->sconn->raw_thread_pool);
+		max_threads = pthreadpool_tevent_max_threads(conn->sconn->pool);
 
 		state->max_async_dosmode_active = lp_smbd_max_async_dosmode(
 							SNUM(conn));
@@ -660,7 +660,7 @@ static bool smb2_query_directory_next_entry(struct tevent_req *req)
 		state->async_dosmode_active++;
 
 		outstanding_aio = pthreadpool_tevent_queued_jobs(
-					state->fsp->conn->sconn->raw_thread_pool);
+					state->fsp->conn->sconn->pool);
 
 		if (outstanding_aio > state->max_async_dosmode_active) {
 			stop = true;
-- 
2.17.1


From 66431d422a45388a701ecc756aae368dc5c0d119 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:42:37 +0100
Subject: [PATCH 17/66] Revert "pthreadpool: test cancelling and freeing jobs
 of a wrapped pthreadpool_tevent"

This reverts commit fb6b6cf3e43165ced4b1039f2683d19f277c0792.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/tests_cmocka.c | 573 ---------------------------------
 1 file changed, 573 deletions(-)

diff --git a/lib/pthreadpool/tests_cmocka.c b/lib/pthreadpool/tests_cmocka.c
index b5b6b4cc624e..5c7f6ab6904b 100644
--- a/lib/pthreadpool/tests_cmocka.c
+++ b/lib/pthreadpool/tests_cmocka.c
@@ -543,9 +543,6 @@ struct test_cancel_state {
 	struct test_cancel_job *job4;
 	struct test_cancel_job *job5;
 	struct test_cancel_job *job6;
-	struct test_cancel_job *job7;
-	struct test_cancel_job *job8;
-	struct test_cancel_job *job9;
 };
 
 static void test_cancel_job(void **private_data)
@@ -808,573 +805,6 @@ static void test_cancel_job(void **private_data)
 	TALLOC_FREE(state);
 }
 
-struct test_pthreadpool_tevent_wrap_tp_stats {
-	unsigned num_before;
-	unsigned num_after;
-	bool destroyed;
-};
-
-struct test_pthreadpool_tevent_wrap_tp_state {
-	struct test_pthreadpool_tevent_wrap_tp_state **selfptr;
-	struct test_pthreadpool_tevent_wrap_tp_stats *stats;
-};
-
-static int test_pthreadpool_tevent_wrap_tp_state_destructor(
-	struct test_pthreadpool_tevent_wrap_tp_state *state)
-{
-	state->stats->destroyed = true;
-	*state->selfptr = NULL;
-
-	return 0;
-}
-
-static bool test_pthreadpool_tevent_tp_before(struct pthreadpool_tevent *wrap,
-					      void *private_data,
-					      struct pthreadpool_tevent *main,
-					      const char *location)
-{
-	struct test_pthreadpool_tevent_wrap_tp_state *state =
-		talloc_get_type_abort(private_data,
-		struct test_pthreadpool_tevent_wrap_tp_state);
-
-	state->stats->num_before++;
-
-	return true;
-}
-
-static bool test_pthreadpool_tevent_tp_after(struct pthreadpool_tevent *wrap,
-					     void *private_data,
-					     struct pthreadpool_tevent *main,
-					     const char *location)
-{
-	struct test_pthreadpool_tevent_wrap_tp_state *state =
-		talloc_get_type_abort(private_data,
-		struct test_pthreadpool_tevent_wrap_tp_state);
-
-	state->stats->num_after++;
-
-	return true;
-}
-
-static const struct pthreadpool_tevent_wrapper_ops test_tp_ops = {
-	.name		= "test_pthreadpool_tevent_tp",
-	.before_job	= test_pthreadpool_tevent_tp_before,
-	.after_job	= test_pthreadpool_tevent_tp_after,
-};
-
-static void test_wrap_cancel_job(void **private_data)
-{
-	struct pthreadpool_tevent_test *t = *private_data;
-	struct tevent_context *ev = t->ev;
-	struct pthreadpool_tevent *poolw1 = NULL;
-	struct test_pthreadpool_tevent_wrap_tp_state *poolw1_state = NULL;
-	struct test_pthreadpool_tevent_wrap_tp_stats poolw1_stats = {
-		.destroyed = false,
-	};
-	struct pthreadpool_tevent *poolw2 = NULL;
-	struct test_pthreadpool_tevent_wrap_tp_state *poolw2_state = NULL;
-	struct test_pthreadpool_tevent_wrap_tp_stats poolw2_stats = {
-		.destroyed = false,
-	};
-	size_t max_threads_o;
-	size_t max_threads_w1;
-	size_t max_threads_w2;
-	bool per_thread_cwd_o;
-	bool per_thread_cwd_w1;
-	bool per_thread_cwd_w2;
-	struct test_cancel_state *state = NULL;
-	int ret;
-	bool ok;
-	int fdpair[2] = { -1, -1 };
-	char c = 0;
-
-	max_threads_o = pthreadpool_tevent_max_threads(t->opool);
-	per_thread_cwd_o = pthreadpool_tevent_per_thread_cwd(t->opool);
-
-	poolw1 = pthreadpool_tevent_wrapper_create(
-		t->opool, t, &test_tp_ops, &poolw1_state,
-		struct test_pthreadpool_tevent_wrap_tp_state);
-	assert_non_null(poolw1);
-	poolw1_state->selfptr = &poolw1_state;
-	ANNOTATE_BENIGN_RACE_SIZED(&poolw1_stats,
-				   sizeof(poolw1_stats),
-				   "protected by pthreadpool_tevent code");
-	poolw1_state->stats = &poolw1_stats;
-	talloc_set_destructor(poolw1_state,
-			      test_pthreadpool_tevent_wrap_tp_state_destructor);
-
-	poolw2 = pthreadpool_tevent_wrapper_create(
-		t->opool, t, &test_tp_ops, &poolw2_state,
-		struct test_pthreadpool_tevent_wrap_tp_state);
-	assert_non_null(poolw2);
-	poolw2_state->selfptr = &poolw2_state;
-	ANNOTATE_BENIGN_RACE_SIZED(&poolw2_stats,
-				   sizeof(poolw2_stats),
-				   "protected by pthreadpool_tevent code");
-	poolw2_state->stats = &poolw2_stats;
-	talloc_set_destructor(poolw2_state,
-			      test_pthreadpool_tevent_wrap_tp_state_destructor);
-
-	assert_false(poolw1_stats.destroyed);
-	assert_int_equal(poolw1_stats.num_before, 0);
-	assert_int_equal(poolw1_stats.num_after, 0);
-	max_threads_w1 = pthreadpool_tevent_max_threads(poolw1);
-	assert_int_equal(max_threads_w1, max_threads_o);
-	per_thread_cwd_w1 = pthreadpool_tevent_per_thread_cwd(poolw1);
-	assert_int_equal(per_thread_cwd_w1, per_thread_cwd_o);
-
-	assert_false(poolw2_stats.destroyed);
-	assert_int_equal(poolw2_stats.num_before, 0);
-	assert_int_equal(poolw2_stats.num_after, 0);
-	max_threads_w2 = pthreadpool_tevent_max_threads(poolw2);
-	assert_int_equal(max_threads_w2, max_threads_o);
-	per_thread_cwd_w2 = pthreadpool_tevent_per_thread_cwd(poolw2);
-	assert_int_equal(per_thread_cwd_w2, per_thread_cwd_o);
-
-	state = talloc_zero(t, struct test_cancel_state);
-	assert_non_null(state);
-	state->job1 = test_cancel_job_create(state);
-	assert_non_null(state->job1);
-	state->job2 = test_cancel_job_create(state);
-	assert_non_null(state->job2);
-	state->job3 = test_cancel_job_create(state);
-	assert_non_null(state->job3);
-
-	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair);
-	assert_int_equal(ret, 0);
-
-	state->job1->fdm = fdpair[0];
-	state->job1->fdj = fdpair[1];
-
-	assert_int_equal(pthreadpool_tevent_queued_jobs(t->opool), 0);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw1), 0);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw2), 0);
-
-	will_return(__wrap_pthread_create, 0);
-	state->job1->req = pthreadpool_tevent_job_send(
-		state->job1, ev, poolw1, test_cancel_job_fn, state->job1);
-	assert_non_null(state->job1->req);
-	tevent_req_set_callback(state->job1->req,
-				test_cancel_job_done,
-				state->job1);
-
-	state->job2->req = pthreadpool_tevent_job_send(
-		state->job2, ev, poolw1, test_cancel_job_fn, NULL);
-	assert_non_null(state->job2->req);
-	tevent_req_set_callback(state->job2->req,
-				test_cancel_job_done,
-				state->job2);
-
-	state->job3->req = pthreadpool_tevent_job_send(
-		state->job3, ev, poolw1, test_cancel_job_fn, NULL);
-	assert_non_null(state->job3->req);
-	tevent_req_set_callback(state->job3->req,
-				test_cancel_job_done,
-				state->job3);
-
-	/*
-	 * Wait for the job 1 to start.
-	 */
-	ret = read(state->job1->fdm, &c, 1);
-	assert_int_equal(ret, 1);
-
-	/*
-	 * We cancel job 3 and destroy job2.
-	 * Both should never be executed.
-	 */
-	assert_int_equal(pthreadpool_tevent_queued_jobs(t->opool), 2);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw1), 2);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw2), 2);
-	TALLOC_FREE(state->job2->req);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(t->opool), 1);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw1), 1);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw2), 1);
-	ok = tevent_req_cancel(state->job3->req);
-	assert_true(ok);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(t->opool), 0);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw1), 0);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw2), 0);
-
-	/*
-	 * Job 3 should complete as canceled, while
-	 * job 1 is still running.
-	 */
-	test_cancel_job_wait(state->job3, ev);
-	assert_int_equal(state->job3->ret, ECANCELED);
-	assert_null(state->job3->req);
-	assert_false(state->job3->started);
-
-	/*
-	 * Now job1 is canceled while it's running,
-	 * this should let it stop it's loop.
-	 */
-	ok = tevent_req_cancel(state->job1->req);
-	assert_false(ok);
-
-	/*
-	 * Job 1 completes, It got at least one sleep
-	 * timeout loop and has state->job1->canceled set.
-	 */
-	test_cancel_job_wait(state->job1, ev);
-	assert_int_equal(state->job1->ret, 0);
-	assert_null(state->job1->req);
-	assert_true(state->job1->started);
-	assert_true(state->job1->finished);
-	assert_true(state->job1->canceled);
-	assert_false(state->job1->orphaned);
-	assert_in_range(state->job1->polls, 1, 100);
-	assert_int_equal(state->job1->timeouts, state->job1->polls);
-
-	assert_false(poolw1_stats.destroyed);
-	assert_int_equal(poolw1_stats.num_before, 1);
-	assert_int_equal(poolw1_stats.num_after, 1);
-
-	assert_int_equal(pthreadpool_tevent_queued_jobs(t->opool), 0);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw1), 0);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw2), 0);
-
-	/*
-	 * Now we create jobs 4 and 5
-	 * Both should execute.
-	 * Job 4 is orphaned while running by a TALLOC_FREE()
-	 * This should stop job 4 and let job 5 start.
-	 * We do a "normal" exit in job 5 by creating some activity
-	 * on the socketpair.
-	 */
-
-	state->job4 = test_cancel_job_create(state);
-	assert_non_null(state->job4);
-
-	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair);
-	assert_int_equal(ret, 0);
-
-	state->job4->fdm = fdpair[0];
-	state->job4->fdj = fdpair[1];
-
-	state->job4->req = pthreadpool_tevent_job_send(
-		state->job4, ev, poolw1, test_cancel_job_fn, state->job4);
-	assert_non_null(state->job4->req);
-	tevent_req_set_callback(state->job4->req,
-				test_cancel_job_done,
-				state->job4);
-
-	state->job5 = test_cancel_job_create(state);
-	assert_non_null(state->job5);
-
-	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair);
-	assert_int_equal(ret, 0);
-
-	state->job5->fdm = fdpair[0];
-	state->job5->fdj = fdpair[1];
-
-	state->job5->req = pthreadpool_tevent_job_send(
-		state->job5, ev, poolw1, test_cancel_job_fn, state->job5);
-	assert_non_null(state->job5->req);
-	tevent_req_set_callback(state->job5->req,
-				test_cancel_job_done,
-				state->job5);
-
-	/*
-	 * Make sure job 5 can exit as soon as possible.
-	 * It will never get a sleep/poll timeout.
-	 */
-	ret = write(state->job5->fdm, &c, 1);
-	assert_int_equal(ret, 1);
-
-	/*
-	 * Wait for the job 4 to start
-	 */
-	ret = read(state->job4->fdm, &c, 1);
-	assert_int_equal(ret, 1);
-
-	assert_false(poolw1_stats.destroyed);
-	assert_int_equal(poolw1_stats.num_before, 2);
-	assert_int_equal(poolw1_stats.num_after, 1);
-
-	assert_int_equal(pthreadpool_tevent_queued_jobs(t->opool), 1);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw1), 1);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw2), 1);
-
-	/*
-	 * destroy the request so that it's marked
-	 * as orphaned.
-	 *
-	 * As we're in the wrapper mode, the
-	 * job thread will exit and try to create
-	 * a new thread.
-	 */
-	TALLOC_FREE(state->job4->req);
-
-	/*
-	 * Job 5 completes, It got no sleep timeout loop.
-	 */
-	will_return(__wrap_pthread_create, 0);
-	test_cancel_job_wait(state->job5, ev);
-	assert_int_equal(state->job5->ret, 0);
-	assert_null(state->job5->req);
-	assert_true(state->job5->started);
-	assert_true(state->job5->finished);
-	assert_false(state->job5->canceled);
-	assert_false(state->job5->orphaned);
-	assert_int_equal(state->job5->polls, 1);
-	assert_int_equal(state->job5->timeouts, 0);
-
-	assert_false(poolw1_stats.destroyed);
-	assert_int_equal(poolw1_stats.num_before, 3);
-	assert_int_equal(poolw1_stats.num_after, 2);
-
-	assert_int_equal(pthreadpool_tevent_queued_jobs(t->opool), 0);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw1), 0);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw2), 0);
-
-	/*
-	 * Job 2 is still not executed as we did a TALLOC_FREE()
-	 * before is was scheduled.
-	 */
-	assert_false(state->job2->completed);
-	assert_false(state->job2->started);
-
-	/*
-	 * Job 4 is still wasn't completed as we did a TALLOC_FREE()
-	 * while it is was running. but it was started and has
-	 * orphaned set
-	 */
-	assert_false(state->job4->completed);
-	assert_true(state->job4->started);
-	assert_true(state->job4->finished);
-	assert_false(state->job4->canceled);
-	assert_true(state->job4->orphaned);
-	assert_in_range(state->job4->polls, 1, 100);
-	assert_int_equal(state->job4->timeouts, state->job4->polls);
-
-	assert_false(poolw1_stats.destroyed);
-	assert_int_equal(poolw1_stats.num_before, 3);
-	assert_int_equal(poolw1_stats.num_after, 2);
-
-	/*
-	 * Now we create jobs 6 and 7
-	 * Both should execute.
-	 * We destroy the pool wrapper (1) while job 6 is executing.
-	 * This should stop job 6 and let job 7 start.
-	 * Job 7 runs on the pool wrapper (2).
-	 * We do a "normal" exit in job 7 by creating some activity
-	 * on the socketpair.
-	 */
-
-	state->job6 = test_cancel_job_create(state);
-	assert_non_null(state->job6);
-
-	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair);
-	assert_int_equal(ret, 0);
-
-	state->job6->fdm = fdpair[0];
-	state->job6->fdj = fdpair[1];
-
-	state->job6->req = pthreadpool_tevent_job_send(
-		state->job6, ev, poolw1, test_cancel_job_fn, state->job6);
-	assert_non_null(state->job6->req);
-	tevent_req_set_callback(state->job6->req,
-				test_cancel_job_done,
-				state->job6);
-
-	state->job7 = test_cancel_job_create(state);
-	assert_non_null(state->job7);
-
-	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair);
-	assert_int_equal(ret, 0);
-
-	state->job7->fdm = fdpair[0];
-	state->job7->fdj = fdpair[1];
-
-	state->job7->req = pthreadpool_tevent_job_send(
-		state->job7, ev, poolw2, test_cancel_job_fn, state->job7);
-	assert_non_null(state->job7->req);
-	tevent_req_set_callback(state->job7->req,
-				test_cancel_job_done,
-				state->job7);
-
-	/*
-	 * Make sure job 7 can exit as soon as possible.
-	 * It will never get a sleep/poll timeout.
-	 */
-	ret = write(state->job7->fdm, &c, 1);
-	assert_int_equal(ret, 1);
-
-	/*
-	 * Wait for the job 6 to start
-	 */
-	ret = read(state->job6->fdm, &c, 1);
-	assert_int_equal(ret, 1);
-
-	assert_non_null(poolw1_state);
-	assert_false(poolw1_stats.destroyed);
-	assert_int_equal(poolw1_stats.num_before, 4);
-	assert_int_equal(poolw1_stats.num_after, 2);
-
-	assert_int_equal(pthreadpool_tevent_queued_jobs(t->opool), 1);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw1), 1);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw2), 1);
-
-	/*
-	 * destroy the request so that it's marked
-	 * as orphaned.
-	 */
-	TALLOC_FREE(poolw1);
-
-	/*
-	 * Wait until the job finished.
-	 */
-	ret = read(state->job6->fdm, &c, 1);
-	assert_int_equal(ret, 0);
-
-	assert_null(poolw1_state);
-	assert_true(poolw1_stats.destroyed);
-	assert_int_equal(poolw1_stats.num_before, 4);
-	assert_int_equal(poolw1_stats.num_after, 2);
-
-	/*
-	 * Job 6 is still dangling arround.
-	 *
-	 * We need to convince valgrind --tool={drd,helgrind}
-	 * that the read above is good enough to be
-	 * sure the job is finished and closed the other end of
-	 * the socketpair.
-	 */
-	ANNOTATE_BENIGN_RACE_SIZED(state->job6,
-				   sizeof(*state->job6),
-				   "protected by thread fence");
-	assert_non_null(state->job6->req);
-	assert_true(tevent_req_is_in_progress(state->job6->req));
-	assert_false(state->job6->completed);
-	assert_true(state->job6->started);
-	assert_true(state->job6->finished);
-	assert_false(state->job6->canceled);
-	assert_true(state->job6->orphaned);
-	assert_in_range(state->job6->polls, 1, 100);
-	assert_int_equal(state->job6->timeouts, state->job4->polls);
-
-	/*
-	 * Job 7 completes, It got no sleep timeout loop.
-	 */
-	will_return(__wrap_pthread_create, 0);
-	test_cancel_job_wait(state->job7, ev);
-	assert_int_equal(state->job7->ret, 0);
-	assert_null(state->job7->req);
-	assert_true(state->job7->started);
-	assert_true(state->job7->finished);
-	assert_false(state->job7->canceled);
-	assert_false(state->job7->orphaned);
-	assert_int_equal(state->job7->polls, 1);
-	assert_int_equal(state->job7->timeouts, 0);
-
-	assert_non_null(poolw2_state);
-	assert_false(poolw2_stats.destroyed);
-	assert_int_equal(poolw2_stats.num_before, 1);
-	assert_int_equal(poolw2_stats.num_after, 1);
-
-	assert_int_equal(pthreadpool_tevent_queued_jobs(t->opool), 0);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(poolw2), 0);
-
-	/*
-	 * Now we create jobs 8
-	 * On a new wrapper pool
-	 * We destroy the main pool while it's executing.
-	 */
-
-	state->job8 = test_cancel_job_create(state);
-	assert_non_null(state->job8);
-
-	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair);
-	assert_int_equal(ret, 0);
-
-	state->job8->fdm = fdpair[0];
-	state->job8->fdj = fdpair[1];
-
-	state->job8->req = pthreadpool_tevent_job_send(
-		state->job8, ev, poolw2, test_cancel_job_fn, state->job8);
-	assert_non_null(state->job8->req);
-	tevent_req_set_callback(state->job8->req,
-				test_cancel_job_done,
-				state->job8);
-
-	/*
-	 * Wait for the job 8 to start
-	 */
-	ret = read(state->job8->fdm, &c, 1);
-	assert_int_equal(ret, 1);
-
-	assert_false(poolw2_stats.destroyed);
-	assert_int_equal(poolw2_stats.num_before, 2);
-	assert_int_equal(poolw2_stats.num_after, 1);
-
-	/*
-	 * destroy the request so that it's marked
-	 * as orphaned.
-	 */
-	TALLOC_FREE(t->opool);
-
-	/*
-	 * Wait until the job finished.
-	 */
-	ret = read(state->job8->fdm, &c, 1);
-	assert_int_equal(ret, 0);
-
-	assert_null(poolw2_state);
-	assert_true(poolw2_stats.destroyed);
-	assert_int_equal(poolw2_stats.num_before, 2);
-	assert_int_equal(poolw2_stats.num_after, 1);
-
-	/*
-	 * Job 8 is still dangling arround.
-	 *
-	 * We need to convince valgrind --tool={drd,helgrind}
-	 * that the read above is good enough to be
-	 * sure the job is finished and closed the other end of
-	 * the socketpair.
-	 */
-	ANNOTATE_BENIGN_RACE_SIZED(state->job8,
-				   sizeof(*state->job8),
-				   "protected by thread fence");
-	assert_non_null(state->job8->req);
-	assert_true(tevent_req_is_in_progress(state->job8->req));
-	assert_false(state->job8->completed);
-	assert_true(state->job8->started);
-	assert_true(state->job8->finished);
-	assert_false(state->job8->canceled);
-	assert_true(state->job8->orphaned);
-	assert_in_range(state->job8->polls, 1, 100);
-	assert_int_equal(state->job8->timeouts, state->job4->polls);
-
-	/*
-	 * Now check that adding a new job to the dangling
-	 * wrapper gives an error.
-	 */
-	state->job9 = test_cancel_job_create(state);
-	assert_non_null(state->job9);
-
-	state->job9->req = pthreadpool_tevent_job_send(
-		state->job9, ev, poolw2, test_cancel_job_fn, state->job9);
-	assert_non_null(state->job9->req);
-	tevent_req_set_callback(state->job9->req,
-				test_cancel_job_done,
-				state->job9);
-
-	/*
-	 * Job 9 completes, But with a failure.
-	 */
-	test_cancel_job_wait(state->job9, ev);
-	assert_int_equal(state->job9->ret, EINVAL);
-	assert_null(state->job9->req);
-	assert_false(state->job9->started);
-	assert_false(state->job9->finished);
-	assert_false(state->job9->canceled);
-	assert_false(state->job9->orphaned);
-	assert_int_equal(state->job9->polls, 0);
-	assert_int_equal(state->job9->timeouts, 0);
-
-	TALLOC_FREE(state);
-}
-
 int main(int argc, char **argv)
 {
 	const struct CMUnitTest tests[] = {
@@ -1387,9 +817,6 @@ int main(int argc, char **argv)
 		cmocka_unit_test_setup_teardown(test_cancel_job,
 						setup_pthreadpool_tevent,
 						teardown_pthreadpool_tevent),
-		cmocka_unit_test_setup_teardown(test_wrap_cancel_job,
-						setup_pthreadpool_tevent,
-						teardown_pthreadpool_tevent),
 	};
 
 	cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
-- 
2.17.1


From e473ebba8863735acb0d3a7816aa5458fb8b1bab Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:42:53 +0100
Subject: [PATCH 18/66] Revert "pthreadpool: implement
 pthreadpool_tevent_wrapper_create() infrastructure"

This reverts commit f9745d8b5234091c38e93ed57a255120b61f3ad7.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool_tevent.c | 402 +--------------------------
 lib/pthreadpool/pthreadpool_tevent.h |  32 ---
 2 files changed, 1 insertion(+), 433 deletions(-)

diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c
index f88f82d17d80..b0a757aa1db5 100644
--- a/lib/pthreadpool/pthreadpool_tevent.c
+++ b/lib/pthreadpool/pthreadpool_tevent.c
@@ -104,8 +104,6 @@ struct pthreadpool_tevent_glue {
 	/* Tuple we are keeping track of in this list. */
 	struct tevent_context *ev;
 	struct tevent_threaded_context *tctx;
-	/* recheck monitor fd event */
-	struct tevent_fd *fde;
 	/* Pointer to link object owned by *ev. */
 	struct pthreadpool_tevent_glue_ev_link *ev_link;
 	/* active jobs */
@@ -125,33 +123,11 @@ struct pthreadpool_tevent_glue_ev_link {
 	struct pthreadpool_tevent_glue *glue;
 };
 
-struct pthreadpool_tevent_wrapper {
-	struct pthreadpool_tevent *main_tp;
-	struct pthreadpool_tevent *wrap_tp;
-	const struct pthreadpool_tevent_wrapper_ops *ops;
-	void *private_state;
-	bool force_per_thread_cwd;
-};
-
 struct pthreadpool_tevent {
-	struct pthreadpool_tevent *prev, *next;
-
 	struct pthreadpool *pool;
 	struct pthreadpool_tevent_glue *glue_list;
 
 	struct pthreadpool_tevent_job *jobs;
-
-	struct {
-		/*
-		 * This is used on the main context
-		 */
-		struct pthreadpool_tevent *list;
-
-		/*
-		 * This is used on the wrapper context
-		 */
-		struct pthreadpool_tevent_wrapper *ctx;
-	} wrapper;
 };
 
 struct pthreadpool_tevent_job_state {
@@ -166,7 +142,6 @@ struct pthreadpool_tevent_job {
 	struct pthreadpool_tevent_job *prev, *next;
 
 	struct pthreadpool_tevent *pool;
-	struct pthreadpool_tevent_wrapper *wrapper;
 	struct pthreadpool_tevent_job_state *state;
 	struct tevent_immediate *im;
 
@@ -206,15 +181,6 @@ struct pthreadpool_tevent_job {
 		 */
 		bool started;
 
-		/*
-		 * 'wrapper'
-		 * set before calling the wrapper before_job() or
-		 * after_job() hooks.
-		 * unset again check the hook finished.
-		 * (only written by job thread!)
-		 */
-		bool wrapper;
-
 		/*
 		 * 'executed'
 		 * set once the job function returned.
@@ -244,18 +210,6 @@ struct pthreadpool_tevent_job {
 		 * (only written by job thread!)
 		 */
 		bool signaled;
-
-		/*
-		 * 'exit_thread'
-		 * maybe set during pthreadpool_tevent_job_fn()
-		 * if some wrapper related code generated an error
-		 * and the environment isn't safe anymore.
-		 *
-		 * In such a case pthreadpool_tevent_job_signal()
-		 * will pick this up and therminate the current
-		 * worker thread by returning -1.
-		 */
-		bool exit_thread; /* only written/read by job thread! */
 	} needs_fence;
 
 	bool per_thread_cwd;
@@ -314,22 +268,8 @@ int pthreadpool_tevent_init(TALLOC_CTX *mem_ctx, unsigned max_threads,
 	return 0;
 }
 
-static struct pthreadpool_tevent *pthreadpool_tevent_unwrap(
-	struct pthreadpool_tevent *pool)
-{
-	struct pthreadpool_tevent_wrapper *wrapper = pool->wrapper.ctx;
-
-	if (wrapper != NULL) {
-		return wrapper->main_tp;
-	}
-
-	return pool;
-}
-
 size_t pthreadpool_tevent_max_threads(struct pthreadpool_tevent *pool)
 {
-	pool = pthreadpool_tevent_unwrap(pool);
-
 	if (pool->pool == NULL) {
 		return 0;
 	}
@@ -339,8 +279,6 @@ size_t pthreadpool_tevent_max_threads(struct pthreadpool_tevent *pool)
 
 size_t pthreadpool_tevent_queued_jobs(struct pthreadpool_tevent *pool)
 {
-	pool = pthreadpool_tevent_unwrap(pool);
-
 	if (pool->pool == NULL) {
 		return 0;
 	}
@@ -350,14 +288,6 @@ size_t pthreadpool_tevent_queued_jobs(struct pthreadpool_tevent *pool)
 
 bool pthreadpool_tevent_per_thread_cwd(struct pthreadpool_tevent *pool)
 {
-	struct pthreadpool_tevent_wrapper *wrapper = pool->wrapper.ctx;
-
-	if (wrapper != NULL && wrapper->force_per_thread_cwd) {
-		return true;
-	}
-
-	pool = pthreadpool_tevent_unwrap(pool);
-
 	if (pool->pool == NULL) {
 		return false;
 	}
@@ -369,94 +299,21 @@ static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool)
 {
 	struct pthreadpool_tevent_job *job = NULL;
 	struct pthreadpool_tevent_job *njob = NULL;
-	struct pthreadpool_tevent *wrap_tp = NULL;
-	struct pthreadpool_tevent *nwrap_tp = NULL;
 	struct pthreadpool_tevent_glue *glue = NULL;
 	int ret;
 
-	if (pool->wrapper.ctx != NULL) {
-		struct pthreadpool_tevent_wrapper *wrapper = pool->wrapper.ctx;
-
-		pool->wrapper.ctx = NULL;
-		pool = wrapper->main_tp;
-
-		DLIST_REMOVE(pool->wrapper.list, wrapper->wrap_tp);
-
-		for (job = pool->jobs; job != NULL; job = njob) {
-			njob = job->next;
-
-			if (job->wrapper != wrapper) {
-				continue;
-			}
-
-			/*
-			 * This removes the job from the list
-			 *
-			 * Note that it waits in case
-			 * the wrapper hooks are currently
-			 * executing on the job.
-			 */
-			pthreadpool_tevent_job_orphan(job);
-		}
-
-		/*
-		 * At this point we're sure that no job
-		 * still references the pthreadpool_tevent_wrapper
-		 * structure, so we can free it.
-		 */
-		TALLOC_FREE(wrapper);
-
-		pthreadpool_tevent_cleanup_orphaned_jobs();
-		return 0;
-	}
-
-	if (pool->pool == NULL) {
-		/*
-		 * A dangling wrapper without main_tp.
-		 */
-		return 0;
-	}
-
 	ret = pthreadpool_stop(pool->pool);
 	if (ret != 0) {
 		return ret;
 	}
 
-	/*
-	 * orphan all jobs (including wrapper jobs)
-	 */
 	for (job = pool->jobs; job != NULL; job = njob) {
 		njob = job->next;
 
-		/*
-		 * The job this removes it from the list
-		 *
-		 * Note that it waits in case
-		 * the wrapper hooks are currently
-		 * executing on the job (thread).
-		 */
+		/* The job this removes it from the list */
 		pthreadpool_tevent_job_orphan(job);
 	}
 
-	/*
-	 * cleanup all existing wrappers, remember we just orphaned
-	 * all jobs (including the once of the wrappers).
-	 *
-	 * So we just mark as broken, so that
-	 * pthreadpool_tevent_job_send() won't accept new jobs.
-	 */
-	for (wrap_tp = pool->wrapper.list; wrap_tp != NULL; wrap_tp = nwrap_tp) {
-		nwrap_tp = wrap_tp->next;
-
-		/*
-		 * Just mark them as broken, so that we can't
-		 * get more jobs.
-		 */
-		TALLOC_FREE(wrap_tp->wrapper.ctx);
-
-		DLIST_REMOVE(pool->wrapper.list, wrap_tp);
-	}
-
 	/*
 	 * Delete all the registered
 	 * tevent_context/tevent_threaded_context
@@ -479,93 +336,12 @@ static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool)
 	return 0;
 }
 
-struct pthreadpool_tevent *_pthreadpool_tevent_wrapper_create(
-				struct pthreadpool_tevent *main_tp,
-				TALLOC_CTX *mem_ctx,
-				const struct pthreadpool_tevent_wrapper_ops *ops,
-				void *pstate,
-				size_t psize,
-				const char *type,
-				const char *location)
-{
-	void **ppstate = (void **)pstate;
-	struct pthreadpool_tevent *wrap_tp = NULL;
-	struct pthreadpool_tevent_wrapper *wrapper = NULL;
-
-	pthreadpool_tevent_cleanup_orphaned_jobs();
-
-	if (main_tp->wrapper.ctx != NULL) {
-		/*
-		 * stacking of wrappers is not supported
-		 */
-		errno = EINVAL;
-		return NULL;
-	}
-
-	if (main_tp->pool == NULL) {
-		/*
-		 * The pool is no longer valid,
-		 * most likely it was a wrapper context
-		 * where the main pool was destroyed.
-		 */
-		errno = EINVAL;
-		return NULL;
-	}
-
-	wrap_tp = talloc_zero(mem_ctx, struct pthreadpool_tevent);
-	if (wrap_tp == NULL) {
-		return NULL;
-	}
-
-	wrapper = talloc_zero(wrap_tp, struct pthreadpool_tevent_wrapper);
-	if (wrapper == NULL) {
-		TALLOC_FREE(wrap_tp);
-		return NULL;
-	}
-	wrapper->main_tp = main_tp;
-	wrapper->wrap_tp = wrap_tp;
-	wrapper->ops = ops;
-	wrapper->private_state = talloc_zero_size(wrapper, psize);
-	if (wrapper->private_state == NULL) {
-		TALLOC_FREE(wrap_tp);
-		return NULL;
-	}
-	talloc_set_name_const(wrapper->private_state, type);
-
-	wrap_tp->wrapper.ctx = wrapper;
-
-	DLIST_ADD_END(main_tp->wrapper.list, wrap_tp);
-
-	talloc_set_destructor(wrap_tp, pthreadpool_tevent_destructor);
-
-	*ppstate = wrapper->private_state;
-	return wrap_tp;
-}
-
-void pthreadpool_tevent_force_per_thread_cwd(struct pthreadpool_tevent *pool,
-					     const void *private_state)
-{
-	struct pthreadpool_tevent_wrapper *wrapper = pool->wrapper.ctx;
-
-	if (wrapper == NULL) {
-		abort();
-	}
-
-	if (wrapper->private_state != private_state) {
-		abort();
-	}
-
-	wrapper->force_per_thread_cwd = true;
-}
-
 static int pthreadpool_tevent_glue_destructor(
 	struct pthreadpool_tevent_glue *glue)
 {
 	struct pthreadpool_tevent_job_state *state = NULL;
 	struct pthreadpool_tevent_job_state *nstate = NULL;
 
-	TALLOC_FREE(glue->fde);
-
 	for (state = glue->states; state != NULL; state = nstate) {
 		nstate = state->next;
 
@@ -606,59 +382,6 @@ static int pthreadpool_tevent_glue_link_destructor(
 	return 0;
 }
 
-static void pthreadpool_tevent_glue_monitor(struct tevent_context *ev,
-					    struct tevent_fd *fde,
-					    uint16_t flags,
-					    void *private_data)
-{
-	struct pthreadpool_tevent_glue *glue =
-		talloc_get_type_abort(private_data,
-		struct pthreadpool_tevent_glue);
-	struct pthreadpool_tevent_job *job = NULL;
-	struct pthreadpool_tevent_job *njob = NULL;
-	int ret = -1;
-
-	ret = pthreadpool_restart_check_monitor_drain(glue->pool->pool);
-	if (ret != 0) {
-		TALLOC_FREE(glue->fde);
-	}
-
-	ret = pthreadpool_restart_check(glue->pool->pool);
-	if (ret == 0) {
-		/*
-		 * success...
-		 */
-		goto done;
-	}
-
-	/*
-	 * There's a problem and the pool
-	 * has not a single thread available
-	 * for pending jobs, so we can only
-	 * stop the jobs and return an error.
-	 * This is similar to a failure from
-	 * pthreadpool_add_job().
-	 */
-	for (job = glue->pool->jobs; job != NULL; job = njob) {
-		njob = job->next;
-
-		tevent_req_defer_callback(job->state->req,
-					  job->state->ev);
-		tevent_req_error(job->state->req, ret);
-	}
-
-done:
-	if (glue->states == NULL) {
-		/*
-		 * If the glue doesn't have any pending jobs
-		 * we remove the glue.
-		 *
-		 * In order to remove the fd event.
-		 */
-		TALLOC_FREE(glue);
-	}
-}
-
 static int pthreadpool_tevent_register_ev(
 				struct pthreadpool_tevent *pool,
 				struct pthreadpool_tevent_job_state *state)
@@ -666,7 +389,6 @@ static int pthreadpool_tevent_register_ev(
 	struct tevent_context *ev = state->ev;
 	struct pthreadpool_tevent_glue *glue = NULL;
 	struct pthreadpool_tevent_glue_ev_link *ev_link = NULL;
-	int monitor_fd = -1;
 
 	/*
 	 * See if this tevent_context was already registered by
@@ -699,28 +421,6 @@ static int pthreadpool_tevent_register_ev(
 	};
 	talloc_set_destructor(glue, pthreadpool_tevent_glue_destructor);
 
-	monitor_fd = pthreadpool_restart_check_monitor_fd(pool->pool);
-	if (monitor_fd == -1 && errno != ENOSYS) {
-		int saved_errno = errno;
-		TALLOC_FREE(glue);
-		return saved_errno;
-	}
-
-	if (monitor_fd != -1) {
-		glue->fde = tevent_add_fd(ev,
-					  glue,
-					  monitor_fd,
-					  TEVENT_FD_READ,
-					  pthreadpool_tevent_glue_monitor,
-					  glue);
-		if (glue->fde == NULL) {
-			close(monitor_fd);
-			TALLOC_FREE(glue);
-			return ENOMEM;
-		}
-		tevent_fd_set_auto_close(glue->fde);
-	}
-
 	/*
 	 * Now allocate the link object to the event context. Note this
 	 * is allocated OFF THE EVENT CONTEXT ITSELF, so if the event
@@ -860,24 +560,6 @@ static void pthreadpool_tevent_job_orphan(struct pthreadpool_tevent_job *job)
 		abort();
 	}
 
-	/*
-	 * Once we marked the request as 'orphaned'
-	 * we spin/loop if 'wrapper' is marked as active.
-	 *
-	 * We need to wait until the wrapper hook finished
-	 * before we can set job->wrapper = NULL.
-	 *
-	 * This is some kind of spinlock, but with
-	 * 1 millisecond sleeps in between, in order
-	 * to give the thread more cpu time to finish.
-	 */
-	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-	while (job->needs_fence.wrapper) {
-		poll(NULL, 0, 1);
-		PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-	}
-	job->wrapper = NULL;
-
 	/*
 	 * Once we marked the request as 'orphaned'
 	 * we spin/loop if it's already marked
@@ -992,14 +674,9 @@ struct tevent_req *pthreadpool_tevent_job_send(
 	struct pthreadpool_tevent_job_state *state = NULL;
 	struct pthreadpool_tevent_job *job = NULL;
 	int ret;
-	struct pthreadpool_tevent_wrapper *wrapper = pool->wrapper.ctx;
 
 	pthreadpool_tevent_cleanup_orphaned_jobs();
 
-	if (wrapper != NULL) {
-		pool = wrapper->main_tp;
-	}
-
 	req = tevent_req_create(mem_ctx, &state,
 				struct pthreadpool_tevent_job_state);
 	if (req == NULL) {
@@ -1029,7 +706,6 @@ struct tevent_req *pthreadpool_tevent_job_send(
 		return tevent_req_post(req, ev);
 	}
 	job->pool = pool;
-	job->wrapper = wrapper;
 	job->fn = fn;
 	job->private_data = private_data;
 	job->im = tevent_create_immediate(state->job);
@@ -1128,73 +804,15 @@ static void pthreadpool_tevent_job_fn(void *private_data)
 	struct pthreadpool_tevent_job *job =
 		talloc_get_type_abort(private_data,
 		struct pthreadpool_tevent_job);
-	struct pthreadpool_tevent_wrapper *wrapper = NULL;
 
 	current_job = job;
 	job->needs_fence.started = true;
 	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-	if (job->needs_fence.orphaned) {
-		current_job = NULL;
-		return;
-	}
-
-	wrapper = job->wrapper;
-	if (wrapper != NULL) {
-		bool ok;
-
-		job->needs_fence.wrapper = true;
-		PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-		if (job->needs_fence.orphaned) {
-			job->needs_fence.wrapper = false;
-			PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-			current_job = NULL;
-			return;
-		}
-		ok = wrapper->ops->before_job(wrapper->wrap_tp,
-					      wrapper->private_state,
-					      wrapper->main_tp,
-					      __location__);
-		job->needs_fence.wrapper = false;
-		PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-		if (!ok) {
-			job->needs_fence.exit_thread = true;
-			PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-			current_job = NULL;
-			return;
-		}
-	}
 
 	job->fn(job->private_data);
 
 	job->needs_fence.executed = true;
 	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-
-	if (wrapper != NULL) {
-		bool ok;
-
-		job->needs_fence.wrapper = true;
-		PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-		if (job->needs_fence.orphaned) {
-			job->needs_fence.wrapper = false;
-			job->needs_fence.exit_thread = true;
-			PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-			current_job = NULL;
-			return;
-		}
-		ok = wrapper->ops->after_job(wrapper->wrap_tp,
-					     wrapper->private_state,
-					     wrapper->main_tp,
-					     __location__);
-		job->needs_fence.wrapper = false;
-		PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-		if (!ok) {
-			job->needs_fence.exit_thread = true;
-			PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-			current_job = NULL;
-			return;
-		}
-	}
-
 	current_job = NULL;
 }
 
@@ -1213,15 +831,6 @@ static int pthreadpool_tevent_job_signal(int jobid,
 		/* Request already gone */
 		job->needs_fence.dropped = true;
 		PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-		if (job->needs_fence.exit_thread) {
-			/*
-			 * A problem with the wrapper the current job/worker
-			 * thread needs to terminate.
-			 *
-			 * The pthreadpool_tevent is already gone.
-			 */
-			return -1;
-		}
 		return 0;
 	}
 
@@ -1247,15 +856,6 @@ static int pthreadpool_tevent_job_signal(int jobid,
 
 	job->needs_fence.signaled = true;
 	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-	if (job->needs_fence.exit_thread) {
-		/*
-		 * A problem with the wrapper the current job/worker
-		 * thread needs to terminate.
-		 *
-		 * The pthreadpool_tevent is already gone.
-		 */
-		return -1;
-	}
 	return 0;
 }
 
diff --git a/lib/pthreadpool/pthreadpool_tevent.h b/lib/pthreadpool/pthreadpool_tevent.h
index 6c939fc1d2d8..ff2ab7cfb73d 100644
--- a/lib/pthreadpool/pthreadpool_tevent.h
+++ b/lib/pthreadpool/pthreadpool_tevent.h
@@ -29,38 +29,6 @@ struct pthreadpool_tevent;
 int pthreadpool_tevent_init(TALLOC_CTX *mem_ctx, unsigned max_threads,
 			    struct pthreadpool_tevent **presult);
 
-struct pthreadpool_tevent_wrapper_ops {
-	const char *name;
-
-	bool (*before_job)(struct pthreadpool_tevent *wrap_tp,
-			   void *private_state,
-			   struct pthreadpool_tevent *main_tp,
-			   const char *location);
-	bool (*after_job)(struct pthreadpool_tevent *wrap_tp,
-			  void *private_state,
-			  struct pthreadpool_tevent *main_tp,
-			  const char *location);
-};
-
-struct pthreadpool_tevent *_pthreadpool_tevent_wrapper_create(
-				struct pthreadpool_tevent *main_tp,
-				TALLOC_CTX *mem_ctx,
-				const struct pthreadpool_tevent_wrapper_ops *ops,
-				void *pstate,
-				size_t psize,
-				const char *type,
-				const char *location);
-#define pthreadpool_tevent_wrapper_create(main_tp, mem_ctx, ops, state, type) \
-	_pthreadpool_tevent_wrapper_create(main_tp, mem_ctx, ops, \
-				       state, sizeof(type), #type, __location__)
-
-/*
- * this can only be called directly after
- * pthreadpool_tevent_wrapper_create()
- */
-void pthreadpool_tevent_force_per_thread_cwd(struct pthreadpool_tevent *pool,
-					     const void *private_state);
-
 size_t pthreadpool_tevent_max_threads(struct pthreadpool_tevent *pool);
 size_t pthreadpool_tevent_queued_jobs(struct pthreadpool_tevent *pool);
 bool pthreadpool_tevent_per_thread_cwd(struct pthreadpool_tevent *pool);
-- 
2.17.1


From c6d3e67b61dd15cf4db2c28c044299508df0330b Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:43:07 +0100
Subject: [PATCH 19/66] Revert "pthreadpool: add
 pthreadpool_restart_check[_monitor_{fd,drain}]()"

This reverts commit 3c4cdb290723432b00ff9ff88b892cb4e66e76cd.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool.c      | 281 -----------------------------
 lib/pthreadpool/pthreadpool.h      |  64 -------
 lib/pthreadpool/pthreadpool_sync.c |  20 --
 3 files changed, 365 deletions(-)

diff --git a/lib/pthreadpool/pthreadpool.c b/lib/pthreadpool/pthreadpool.c
index d482c1599410..c2bafd52c08b 100644
--- a/lib/pthreadpool/pthreadpool.c
+++ b/lib/pthreadpool/pthreadpool.c
@@ -24,7 +24,6 @@
 #include "system/filesys.h"
 #include "pthreadpool.h"
 #include "lib/util/dlinklist.h"
-#include "lib/util/blocking.h"
 
 #ifdef NDEBUG
 #undef NDEBUG
@@ -54,8 +53,6 @@ struct pthreadpool {
 	 */
 	pthread_cond_t condvar;
 
-	int check_pipefd[2];
-
 	/*
 	 * Array of jobs
 	 */
@@ -140,7 +137,6 @@ int pthreadpool_init(unsigned max_threads, struct pthreadpool **presult,
 {
 	struct pthreadpool *pool;
 	int ret;
-	bool ok;
 
 	pool = (struct pthreadpool *)malloc(sizeof(struct pthreadpool));
 	if (pool == NULL) {
@@ -158,52 +154,10 @@ int pthreadpool_init(unsigned max_threads, struct pthreadpool **presult,
 		return ENOMEM;
 	}
 
-	ret = pipe(pool->check_pipefd);
-	if (ret != 0) {
-		free(pool->jobs);
-		free(pool);
-		return ENOMEM;
-	}
-
-	ok = smb_set_close_on_exec(pool->check_pipefd[0]);
-	if (!ok) {
-		close(pool->check_pipefd[0]);
-		close(pool->check_pipefd[1]);
-		free(pool->jobs);
-		free(pool);
-		return EINVAL;
-	}
-	ok = smb_set_close_on_exec(pool->check_pipefd[1]);
-	if (!ok) {
-		close(pool->check_pipefd[0]);
-		close(pool->check_pipefd[1]);
-		free(pool->jobs);
-		free(pool);
-		return EINVAL;
-	}
-	ret = set_blocking(pool->check_pipefd[0], true);
-	if (ret == -1) {
-		close(pool->check_pipefd[0]);
-		close(pool->check_pipefd[1]);
-		free(pool->jobs);
-		free(pool);
-		return EINVAL;
-	}
-	ret = set_blocking(pool->check_pipefd[1], false);
-	if (ret == -1) {
-		close(pool->check_pipefd[0]);
-		close(pool->check_pipefd[1]);
-		free(pool->jobs);
-		free(pool);
-		return EINVAL;
-	}
-
 	pool->head = pool->num_jobs = 0;
 
 	ret = pthread_mutex_init(&pool->mutex, NULL);
 	if (ret != 0) {
-		close(pool->check_pipefd[0]);
-		close(pool->check_pipefd[1]);
 		free(pool->jobs);
 		free(pool);
 		return ret;
@@ -212,8 +166,6 @@ int pthreadpool_init(unsigned max_threads, struct pthreadpool **presult,
 	ret = pthread_cond_init(&pool->condvar, NULL);
 	if (ret != 0) {
 		pthread_mutex_destroy(&pool->mutex);
-		close(pool->check_pipefd[0]);
-		close(pool->check_pipefd[1]);
 		free(pool->jobs);
 		free(pool);
 		return ret;
@@ -223,8 +175,6 @@ int pthreadpool_init(unsigned max_threads, struct pthreadpool **presult,
 	if (ret != 0) {
 		pthread_cond_destroy(&pool->condvar);
 		pthread_mutex_destroy(&pool->mutex);
-		close(pool->check_pipefd[0]);
-		close(pool->check_pipefd[1]);
 		free(pool->jobs);
 		free(pool);
 		return ret;
@@ -247,8 +197,6 @@ int pthreadpool_init(unsigned max_threads, struct pthreadpool **presult,
 		pthread_mutex_destroy(&pool->fork_mutex);
 		pthread_cond_destroy(&pool->condvar);
 		pthread_mutex_destroy(&pool->mutex);
-		close(pool->check_pipefd[0]);
-		close(pool->check_pipefd[1]);
 		free(pool->jobs);
 		free(pool);
 		return ret;
@@ -412,14 +360,6 @@ static void pthreadpool_child(void)
 		pool->head = 0;
 		pool->num_jobs = 0;
 		pool->stopped = true;
-		if (pool->check_pipefd[0] != -1) {
-			close(pool->check_pipefd[0]);
-			pool->check_pipefd[0] = -1;
-		}
-		if (pool->check_pipefd[1] != -1) {
-			close(pool->check_pipefd[1]);
-			pool->check_pipefd[1] = -1;
-		}
 
 		ret = pthread_cond_init(&pool->condvar, NULL);
 		assert(ret == 0);
@@ -482,14 +422,6 @@ static int pthreadpool_free(struct pthreadpool *pool)
 		return ret2;
 	}
 
-	if (pool->check_pipefd[0] != -1) {
-		close(pool->check_pipefd[0]);
-		pool->check_pipefd[0] = -1;
-	}
-	if (pool->check_pipefd[1] != -1) {
-		close(pool->check_pipefd[1]);
-		pool->check_pipefd[1] = -1;
-	}
 	free(pool->jobs);
 	free(pool);
 
@@ -506,15 +438,6 @@ static int pthreadpool_stop_locked(struct pthreadpool *pool)
 
 	pool->stopped = true;
 
-	if (pool->check_pipefd[0] != -1) {
-		close(pool->check_pipefd[0]);
-		pool->check_pipefd[0] = -1;
-	}
-	if (pool->check_pipefd[1] != -1) {
-		close(pool->check_pipefd[1]);
-		pool->check_pipefd[1] = -1;
-	}
-
 	if (pool->num_threads == 0) {
 		return 0;
 	}
@@ -599,33 +522,6 @@ static void pthreadpool_server_exit(struct pthreadpool *pool)
 
 	free_it = (pool->destroyed && (pool->num_threads == 0));
 
-	while (true) {
-		uint8_t c = 0;
-		ssize_t nwritten = 0;
-
-		if (pool->check_pipefd[1] == -1) {
-			break;
-		}
-
-		nwritten = write(pool->check_pipefd[1], &c, 1);
-		if (nwritten == -1) {
-			if (errno == EINTR) {
-				continue;
-			}
-			if (errno == EAGAIN) {
-				break;
-			}
-#ifdef EWOULDBLOCK
-			if (errno == EWOULDBLOCK) {
-				break;
-			}
-#endif
-			/* ignore ... */
-		}
-
-		break;
-	}
-
 	ret = pthread_mutex_unlock(&pool->mutex);
 	assert(ret == 0);
 
@@ -956,183 +852,6 @@ int pthreadpool_add_job(struct pthreadpool *pool, int job_id,
 	return res;
 }
 
-int pthreadpool_restart_check(struct pthreadpool *pool)
-{
-	int res;
-	int unlock_res;
-	unsigned possible_threads = 0;
-	unsigned missing_threads = 0;
-
-	assert(!pool->destroyed);
-
-	res = pthread_mutex_lock(&pool->mutex);
-	if (res != 0) {
-		return res;
-	}
-
-	if (pool->stopped) {
-		/*
-		 * Protect against the pool being shut down while
-		 * trying to add a job
-		 */
-		unlock_res = pthread_mutex_unlock(&pool->mutex);
-		assert(unlock_res == 0);
-		return EINVAL;
-	}
-
-	if (pool->num_jobs == 0) {
-		/*
-		 * This also handles the pool->max_threads == 0 case as it never
-		 * calls pthreadpool_put_job()
-		 */
-		unlock_res = pthread_mutex_unlock(&pool->mutex);
-		assert(unlock_res == 0);
-		return 0;
-	}
-
-	if (pool->num_idle > 0) {
-		/*
-		 * We have idle threads and pending jobs,
-		 * this means we better let all threads
-		 * start and check for pending jobs.
-		 */
-		res = pthread_cond_broadcast(&pool->condvar);
-		assert(res == 0);
-	}
-
-	if (pool->num_threads < pool->max_threads) {
-		possible_threads = pool->max_threads - pool->num_threads;
-	}
-
-	if (pool->num_idle < pool->num_jobs) {
-		missing_threads = pool->num_jobs - pool->num_idle;
-	}
-
-	missing_threads = MIN(missing_threads, possible_threads);
-
-	while (missing_threads > 0) {
-
-		res = pthreadpool_create_thread(pool);
-		if (res != 0) {
-			break;
-		}
-
-		missing_threads--;
-	}
-
-	if (missing_threads == 0) {
-		/*
-		 * Ok, we recreated all thread we need.
-		 */
-		unlock_res = pthread_mutex_unlock(&pool->mutex);
-		assert(unlock_res == 0);
-		return 0;
-	}
-
-	if (pool->num_threads != 0) {
-		/*
-		 * At least one thread is still available, let
-		 * that one run the queued jobs.
-		 */
-		unlock_res = pthread_mutex_unlock(&pool->mutex);
-		assert(unlock_res == 0);
-		return 0;
-	}
-
-	/*
-	 * There's no thread available to run any pending jobs.
-	 * The caller may want to cancel the jobs and destroy the pool.
-	 * But that's up to the caller.
-	 */
-	unlock_res = pthread_mutex_unlock(&pool->mutex);
-	assert(unlock_res == 0);
-
-	return res;
-}
-
-int pthreadpool_restart_check_monitor_fd(struct pthreadpool *pool)
-{
-	int fd;
-	int ret;
-	bool ok;
-
-	if (pool->stopped) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	if (pool->check_pipefd[0] == -1) {
-		errno = ENOSYS;
-		return -1;
-	}
-
-	fd = dup(pool->check_pipefd[0]);
-	if (fd == -1) {
-		return -1;
-	}
-
-	ok = smb_set_close_on_exec(fd);
-	if (!ok) {
-		int saved_errno = errno;
-		close(fd);
-		errno = saved_errno;
-		return -1;
-	}
-
-	ret = set_blocking(fd, false);
-	if (ret == -1) {
-		int saved_errno = errno;
-		close(fd);
-		errno = saved_errno;
-		return -1;
-	}
-
-	return fd;
-}
-
-int pthreadpool_restart_check_monitor_drain(struct pthreadpool *pool)
-{
-	if (pool->stopped) {
-		return EINVAL;
-	}
-
-	if (pool->check_pipefd[0] == -1) {
-		return ENOSYS;
-	}
-
-	while (true) {
-		uint8_t buf[128];
-		ssize_t nread;
-
-		nread = read(pool->check_pipefd[0], buf, sizeof(buf));
-		if (nread == -1) {
-			if (errno == EINTR) {
-				continue;
-			}
-			if (errno == EAGAIN) {
-				return 0;
-			}
-#ifdef EWOULDBLOCK
-			if (errno == EWOULDBLOCK) {
-				return 0;
-			}
-#endif
-			if (errno == 0) {
-				errno = INT_MAX;
-			}
-
-			return errno;
-		}
-
-		if (nread < sizeof(buf)) {
-			return 0;
-		}
-	}
-
-	abort();
-	return INT_MAX;
-}
-
 size_t pthreadpool_cancel_job(struct pthreadpool *pool, int job_id,
 			      void (*fn)(void *private_data), void *private_data)
 {
diff --git a/lib/pthreadpool/pthreadpool.h b/lib/pthreadpool/pthreadpool.h
index 543567ceaf78..d8daf9e4519b 100644
--- a/lib/pthreadpool/pthreadpool.h
+++ b/lib/pthreadpool/pthreadpool.h
@@ -144,70 +144,6 @@ int pthreadpool_destroy(struct pthreadpool *pool);
 int pthreadpool_add_job(struct pthreadpool *pool, int job_id,
 			void (*fn)(void *private_data), void *private_data);
 
-/**
- * @brief Check if the pthreadpool needs a restart.
- *
- * This checks if there are enough threads to run the already
- * queued jobs. This should be called only the callers signal_fn
- * (passed to pthreadpool_init()) returned an error, so
- * that the job's worker thread exited.
- *
- * Typically this is called once the file destriptor
- * returned by pthreadpool_restart_check_monitor_fd()
- * became readable and pthreadpool_restart_check_monitor_drain()
- * returned success.
- *
- * This function tries to restart the missing threads.
- *
- * @param[in]	pool		The pool to run the job on
- * @return			success: 0, failure: errno
- *
- * @see pthreadpool_restart_check_monitor_fd
- * @see pthreadpool_restart_check_monitor_drain
- */
-int pthreadpool_restart_check(struct pthreadpool *pool);
-
-/**
- * @brief Return a file destriptor that monitors the pool.
- *
- * If the file destrictor becomes readable,
- * the event handler should call pthreadpool_restart_check_monitor_drain().
- *
- * pthreadpool_restart_check() should also be called once the
- * state is drained.
- *
- * This function returns a fresh fd using dup() each time.
- *
- * If the pool doesn't require restarts, this function
- * returns -1 and sets errno = ENOSYS. The caller
- * may ignore that situation.
- *
- * @param[in]	pool		The pool to run the job on
- * @return			success: 0, failure: -1 (set errno)
- *
- * @see pthreadpool_restart_check_monitor_fd
- * @see pthreadpool_restart_check_monitor_drain
- */
-int pthreadpool_restart_check_monitor_fd(struct pthreadpool *pool);
-
-/**
- * @brief Drain the monitor file destriptor of the pool.
- *
- * If the file destrictor returned by pthreadpool_restart_check_monitor_fd()
- * becomes readable, pthreadpool_restart_check_monitor_drain() should be
- * called before pthreadpool_restart_check().
- *
- * If this function returns an error the caller should close
- * the file destriptor it got from pthreadpool_restart_check_monitor_fd().
- *
- * @param[in]	pool		The pool to run the job on
- * @return			success: 0, failure: errno
- *
- * @see pthreadpool_restart_check_monitor_fd
- * @see pthreadpool_restart_check
- */
-int pthreadpool_restart_check_monitor_drain(struct pthreadpool *pool);
-
 /**
  * @brief Try to cancel a job in a pthreadpool
  *
diff --git a/lib/pthreadpool/pthreadpool_sync.c b/lib/pthreadpool/pthreadpool_sync.c
index a476ea712c3a..2ed6f36dbbc7 100644
--- a/lib/pthreadpool/pthreadpool_sync.c
+++ b/lib/pthreadpool/pthreadpool_sync.c
@@ -83,26 +83,6 @@ int pthreadpool_add_job(struct pthreadpool *pool, int job_id,
 			       pool->signal_fn_private_data);
 }
 
-int pthreadpool_restart_check(struct pthreadpool *pool)
-{
-	if (pool->stopped) {
-		return EINVAL;
-	}
-
-	return 0;
-}
-
-int pthreadpool_restart_check_monitor_fd(struct pthreadpool *pool)
-{
-	errno = ENOSYS;
-	return -1;
-}
-
-int pthreadpool_restart_check_monitor_drain(struct pthreadpool *pool)
-{
-	return EINVAL;
-}
-
 size_t pthreadpool_cancel_job(struct pthreadpool *pool, int job_id,
 			      void (*fn)(void *private_data), void *private_data)
 {
-- 
2.17.1


From d6a6ae496d34e6e35d6bdf79edc6af58031f6ee8 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 7 Jan 2019 18:35:27 +0100
Subject: [PATCH 20/66] Revert "pthreadpool: call unshare(CLONE_FS) if
 available"

This reverts commit 65e4742d168454df6507d9e74993749063435dd6.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool.c      | 34 ------------------------------
 lib/pthreadpool/pthreadpool.h      | 17 ---------------
 lib/pthreadpool/pthreadpool_sync.c |  5 -----
 3 files changed, 56 deletions(-)

diff --git a/lib/pthreadpool/pthreadpool.c b/lib/pthreadpool/pthreadpool.c
index c2bafd52c08b..b6dad310b0da 100644
--- a/lib/pthreadpool/pthreadpool.c
+++ b/lib/pthreadpool/pthreadpool.c
@@ -113,13 +113,10 @@ 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);
@@ -186,11 +183,6 @@ 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) {
@@ -250,15 +242,6 @@ 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;
@@ -377,16 +360,6 @@ 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);
 }
@@ -599,13 +572,6 @@ 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 d8daf9e4519b..b4733580e07b 100644
--- a/lib/pthreadpool/pthreadpool.h
+++ b/lib/pthreadpool/pthreadpool.h
@@ -71,23 +71,6 @@ 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
  *
diff --git a/lib/pthreadpool/pthreadpool_sync.c b/lib/pthreadpool/pthreadpool_sync.c
index 2ed6f36dbbc7..48e6a0ddb604 100644
--- a/lib/pthreadpool/pthreadpool_sync.c
+++ b/lib/pthreadpool/pthreadpool_sync.c
@@ -65,11 +65,6 @@ 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)
 {
-- 
2.17.1


From 1fdad6daeffd6a2be8743615d8a572a767f1131f Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:43:25 +0100
Subject: [PATCH 21/66] Revert "pthreadpool: add tests for
 pthreadpool_tevent_[current_job_]per_thread_cwd()"

This reverts commit fbafdc99ef2cef11a1a28e795ffe965cb53ef7fa.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/tests_cmocka.c | 144 ---------------------------------
 1 file changed, 144 deletions(-)

diff --git a/lib/pthreadpool/tests_cmocka.c b/lib/pthreadpool/tests_cmocka.c
index 5c7f6ab6904b..dc7b1150b5c0 100644
--- a/lib/pthreadpool/tests_cmocka.c
+++ b/lib/pthreadpool/tests_cmocka.c
@@ -244,147 +244,6 @@ static void test_create(void **state)
 	assert_false(in_main_thread);
 }
 
-static void test_per_thread_cwd_job(void *ptr)
-{
-	const bool *per_thread_cwd_ptr = ptr;
-	bool per_thread_cwd;
-	char cwdbuf[PATH_MAX] = {0,};
-	char *cwdstr = NULL;
-	int ret;
-
-	/*
-	 * This needs to be consistent.
-	 */
-	per_thread_cwd = pthreadpool_tevent_current_job_per_thread_cwd();
-	assert_int_equal(per_thread_cwd, *per_thread_cwd_ptr);
-
-	if (!per_thread_cwd) {
-		return;
-	}
-
-	/*
-	 * Check we're not already in "/".
-	 */
-	cwdstr = getcwd(cwdbuf, sizeof(cwdbuf));
-	assert_non_null(cwdstr);
-	assert_string_not_equal(cwdstr, "/");
-
-	ret = chdir("/");
-	assert_int_equal(ret, 0);
-
-	/*
-	 * Check we're in "/" now.
-	 */
-	cwdstr = getcwd(cwdbuf, sizeof(cwdbuf));
-	assert_non_null(cwdstr);
-	assert_string_equal(cwdstr, "/");
-}
-
-static int test_per_thread_cwd_do(struct tevent_context *ev,
-				  struct pthreadpool_tevent *pool)
-{
-	struct tevent_req *req;
-	bool per_thread_cwd;
-	bool ok;
-	int ret;
-	per_thread_cwd = pthreadpool_tevent_per_thread_cwd(pool);
-
-	req = pthreadpool_tevent_job_send(
-		ev, ev, pool, test_per_thread_cwd_job, &per_thread_cwd);
-	if (req == NULL) {
-		fprintf(stderr, "pthreadpool_tevent_job_send failed\n");
-		return ENOMEM;
-	}
-
-	ok = tevent_req_poll(req, ev);
-	if (!ok) {
-		ret = errno;
-		fprintf(stderr, "tevent_req_poll failed: %s\n",
-			strerror(ret));
-		return ret;
-	}
-
-	ret = pthreadpool_tevent_job_recv(req);
-	TALLOC_FREE(req);
-	if (ret != 0) {
-		fprintf(stderr, "tevent_req_recv failed: %s\n",
-			strerror(ret));
-		return ret;
-	}
-
-	return 0;
-}
-
-static void test_per_thread_cwd(void **state)
-{
-	struct pthreadpool_tevent_test *t = *state;
-	int ret;
-	bool per_thread_cwd_u;
-	bool per_thread_cwd_o;
-	bool per_thread_cwd_s;
-	char cwdbuf1[PATH_MAX] = {0,};
-	char *cwdstr1 = NULL;
-	char cwdbuf2[PATH_MAX] = {0,};
-	char *cwdstr2 = NULL;
-
-	/*
-	 * The unlimited and one pools
-	 * should be consistent.
-	 *
-	 * We can't enforce this as some constraint
-	 * container environments disable unshare()
-	 * completely, even just with CLONE_FS.
-	 */
-	per_thread_cwd_u = pthreadpool_tevent_per_thread_cwd(t->upool);
-	per_thread_cwd_o = pthreadpool_tevent_per_thread_cwd(t->opool);
-	assert_int_equal(per_thread_cwd_u, per_thread_cwd_o);
-
-	/*
-	 * The sync pool should never support this.
-	 */
-	per_thread_cwd_s = pthreadpool_tevent_per_thread_cwd(t->spool);
-	assert_false(per_thread_cwd_s);
-
-	/*
-	 * Check we're not already in "/".
-	 */
-	cwdstr1 = getcwd(cwdbuf1, sizeof(cwdbuf1));
-	assert_non_null(cwdstr1);
-	assert_string_not_equal(cwdstr1, "/");
-
-	will_return(__wrap_pthread_create, 0);
-	ret = test_per_thread_cwd_do(t->ev, t->upool);
-	assert_int_equal(ret, 0);
-
-	/*
-	 * Check we're still in the same directory.
-	 */
-	cwdstr2 = getcwd(cwdbuf2, sizeof(cwdbuf2));
-	assert_non_null(cwdstr2);
-	assert_string_equal(cwdstr2, cwdstr1);
-
-	will_return(__wrap_pthread_create, 0);
-	ret = test_per_thread_cwd_do(t->ev, t->opool);
-	assert_int_equal(ret, 0);
-
-	/*
-	 * Check we're still in the same directory.
-	 */
-	cwdstr2 = getcwd(cwdbuf2, sizeof(cwdbuf2));
-	assert_non_null(cwdstr2);
-	assert_string_equal(cwdstr2, cwdstr1);
-
-	ret = test_per_thread_cwd_do(t->ev, t->spool);
-	assert_int_equal(ret, 0);
-
-	/*
-	 * Check we're still in the same directory.
-	 */
-	cwdstr2 = getcwd(cwdbuf2, sizeof(cwdbuf2));
-	assert_non_null(cwdstr2);
-	assert_string_equal(cwdstr2, cwdstr1);
-}
-
 struct test_cancel_job {
 	int fdm; /* the main end of socketpair */
 	int fdj; /* the job end of socketpair */
@@ -811,9 +670,6 @@ int main(int argc, char **argv)
 		cmocka_unit_test_setup_teardown(test_create,
 						setup_pthreadpool_tevent,
 						teardown_pthreadpool_tevent),
-		cmocka_unit_test_setup_teardown(test_per_thread_cwd,
-						setup_pthreadpool_tevent,
-						teardown_pthreadpool_tevent),
 		cmocka_unit_test_setup_teardown(test_cancel_job,
 						setup_pthreadpool_tevent,
 						teardown_pthreadpool_tevent),
-- 
2.17.1


From b57fefd49ce50ebdf7e18ae06e5881cbce62d06f Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 7 Jan 2019 21:27:19 +0100
Subject: [PATCH 22/66] Revert "pthreadpool: add
 pthreadpool_tevent_[current_job_]per_thread_cwd()"

This reverts commit 12a45ee1a66379ba7562729b835ce0e2e4bfb3b3.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool_tevent.c | 26 --------------------------
 lib/pthreadpool/pthreadpool_tevent.h |  7 -------
 2 files changed, 33 deletions(-)

diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c
index b0a757aa1db5..5ccff6231f0b 100644
--- a/lib/pthreadpool/pthreadpool_tevent.c
+++ b/lib/pthreadpool/pthreadpool_tevent.c
@@ -211,8 +211,6 @@ struct pthreadpool_tevent_job {
 		 */
 		bool signaled;
 	} needs_fence;
-
-	bool per_thread_cwd;
 };
 
 static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool);
@@ -286,15 +284,6 @@ size_t pthreadpool_tevent_queued_jobs(struct pthreadpool_tevent *pool)
 	return pthreadpool_queued_jobs(pool->pool);
 }
 
-bool pthreadpool_tevent_per_thread_cwd(struct pthreadpool_tevent *pool)
-{
-	if (pool->pool == NULL) {
-		return false;
-	}
-
-	return pthreadpool_per_thread_cwd(pool->pool);
-}
-
 static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool)
 {
 	struct pthreadpool_tevent_job *job = NULL;
@@ -713,7 +702,6 @@ struct tevent_req *pthreadpool_tevent_job_send(
 		return tevent_req_post(req, ev);
 	}
 	PTHREAD_TEVENT_JOB_THREAD_FENCE_INIT(job);
-	job->per_thread_cwd = pthreadpool_tevent_per_thread_cwd(pool);
 	talloc_set_destructor(job, pthreadpool_tevent_job_destructor);
 	DLIST_ADD_END(job->pool->jobs, job);
 	job->state = state;
@@ -785,20 +773,6 @@ bool pthreadpool_tevent_current_job_continue(void)
 	return true;
 }
 
-bool pthreadpool_tevent_current_job_per_thread_cwd(void)
-{
-	if (current_job == NULL) {
-		/*
-		 * Should only be called from within
-		 * the job function.
-		 */
-		abort();
-		return false;
-	}
-
-	return current_job->per_thread_cwd;
-}
-
 static void pthreadpool_tevent_job_fn(void *private_data)
 {
 	struct pthreadpool_tevent_job *job =
diff --git a/lib/pthreadpool/pthreadpool_tevent.h b/lib/pthreadpool/pthreadpool_tevent.h
index ff2ab7cfb73d..37e491e17c47 100644
--- a/lib/pthreadpool/pthreadpool_tevent.h
+++ b/lib/pthreadpool/pthreadpool_tevent.h
@@ -31,7 +31,6 @@ int pthreadpool_tevent_init(TALLOC_CTX *mem_ctx, unsigned max_threads,
 
 size_t pthreadpool_tevent_max_threads(struct pthreadpool_tevent *pool);
 size_t pthreadpool_tevent_queued_jobs(struct pthreadpool_tevent *pool);
-bool pthreadpool_tevent_per_thread_cwd(struct pthreadpool_tevent *pool);
 
 /*
  * return true - if tevent_req_cancel() was called.
@@ -47,12 +46,6 @@ bool pthreadpool_tevent_current_job_orphaned(void);
  */
 bool pthreadpool_tevent_current_job_continue(void);
 
-/*
- * return true if the current job can rely on a per thread
- * current working directory.
- */
-bool pthreadpool_tevent_current_job_per_thread_cwd(void);
-
 struct tevent_req *pthreadpool_tevent_job_send(
 	TALLOC_CTX *mem_ctx, struct tevent_context *ev,
 	struct pthreadpool_tevent *pool,
-- 
2.17.1


From 476048d684ba7208ea84090752f95ec18192bdf4 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:44:07 +0100
Subject: [PATCH 23/66] Revert "pthreadpool: test cancelling and freeing
 pending pthreadpool_tevent jobs/pools"

This reverts commit 40d15260d24d0071732f47873f395fce29b8a6f4.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/tests_cmocka.c | 434 ---------------------------------
 1 file changed, 434 deletions(-)

diff --git a/lib/pthreadpool/tests_cmocka.c b/lib/pthreadpool/tests_cmocka.c
index dc7b1150b5c0..e6af8849f01d 100644
--- a/lib/pthreadpool/tests_cmocka.c
+++ b/lib/pthreadpool/tests_cmocka.c
@@ -17,16 +17,12 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "config.h"
 #include <errno.h>
 #include <pthread.h>
 #include <setjmp.h>
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
 
 #include <talloc.h>
 #include <tevent.h>
@@ -35,13 +31,6 @@
 #include <cmocka.h>
 #include <poll.h>
 
-#ifdef HAVE_VALGRIND_HELGRIND_H
-#include <valgrind/helgrind.h>
-#endif
-#ifndef ANNOTATE_BENIGN_RACE_SIZED
-#define ANNOTATE_BENIGN_RACE_SIZED(address, size, describtion)
-#endif
-
 struct pthreadpool_tevent_test {
 	struct tevent_context *ev;
 	struct pthreadpool_tevent *upool;
@@ -244,435 +233,12 @@ static void test_create(void **state)
 	assert_false(in_main_thread);
 }
 
-struct test_cancel_job {
-	int fdm; /* the main end of socketpair */
-	int fdj; /* the job end of socketpair */
-	bool started;
-	bool canceled;
-	bool orphaned;
-	bool finished;
-	size_t polls;
-	size_t timeouts;
-	int sleep_msec;
-	struct tevent_req *req;
-	bool completed;
-	int ret;
-};
-
-static void test_cancel_job_done(struct tevent_req *req);
-
-static int test_cancel_job_destructor(struct test_cancel_job *job)
-{
-	ANNOTATE_BENIGN_RACE_SIZED(&job->started,
-				   sizeof(job->started),
-				   "protected by pthreadpool_tevent code");
-	if (job->started) {
-		ANNOTATE_BENIGN_RACE_SIZED(&job->finished,
-					   sizeof(job->finished),
-					   "protected by pthreadpool_tevent code");
-		assert_true(job->finished);
-	}
-
-	ANNOTATE_BENIGN_RACE_SIZED(&job->fdj,
-				   sizeof(job->fdj),
-				   "protected by pthreadpool_tevent code");
-
-	if (job->fdm != -1) {
-		close(job->fdm);
-		job->fdm = -1;
-	}
-	if (job->fdj != -1) {
-		close(job->fdj);
-		job->fdj = -1;
-	}
-
-	return 0;
-}
-
-static struct test_cancel_job *test_cancel_job_create(TALLOC_CTX *mem_ctx)
-{
-	struct test_cancel_job *job = NULL;
-
-	job = talloc(mem_ctx, struct test_cancel_job);
-	if (job == NULL) {
-		return NULL;
-	}
-	*job = (struct test_cancel_job) {
-		.fdm = -1,
-		.fdj = -1,
-		.sleep_msec = 50,
-	};
-
-	talloc_set_destructor(job, test_cancel_job_destructor);
-	return job;
-}
-
-static void test_cancel_job_fn(void *ptr)
-{
-	struct test_cancel_job *job = (struct test_cancel_job *)ptr;
-	int fdj = -1;
-	char c = 0;
-	int ret;
-
-	assert_non_null(job); /* make sure we abort without a job pointer */
-
-	job->started = true;
-	fdj = job->fdj;
-	job->fdj = -1;
-
-	if (!pthreadpool_tevent_current_job_continue()) {
-		job->canceled = pthreadpool_tevent_current_job_canceled();
-		job->orphaned = pthreadpool_tevent_current_job_orphaned();
-		job->finished = true;
-		close(fdj);
-		return;
-	}
-
-	/*
-	 * Notify that we main thread
-	 *
-	 * write of 1 byte should always work!
-	 */
-	ret = write(fdj, &c, 1);
-	assert_int_equal(ret, 1);
-
-	/*
-	 * loop until the job was tried to
-	 * be canceled or becomes orphaned.
-	 *
-	 * If there's some activity on the fd
-	 * we directly finish.
-	 */
-	do {
-		struct pollfd pfd = {
-			.fd = fdj,
-			.events = POLLIN,
-		};
-
-		job->polls += 1;
-
-		ret = poll(&pfd, 1, job->sleep_msec);
-		if (ret == 1) {
-			job->finished = true;
-			close(fdj);
-			return;
-		}
-		assert_int_equal(ret, 0);
-
-		job->timeouts += 1;
-
-	} while (pthreadpool_tevent_current_job_continue());
-
-	job->canceled = pthreadpool_tevent_current_job_canceled();
-	job->orphaned = pthreadpool_tevent_current_job_orphaned();
-	job->finished = true;
-	close(fdj);
-}
-
-static void test_cancel_job_done(struct tevent_req *req)
-{
-	struct test_cancel_job *job =
-		tevent_req_callback_data(req,
-		struct test_cancel_job);
-
-	job->ret = pthreadpool_tevent_job_recv(job->req);
-	TALLOC_FREE(job->req);
-	job->completed = true;
-}
-
-static void test_cancel_job_wait(struct test_cancel_job *job,
-				 struct tevent_context *ev)
-{
-	/*
-	 * We have to keep looping until
-	 * test_cancel_job_done was triggered
-	 */
-	while (!job->completed) {
-		int ret;
-
-		ret = tevent_loop_once(ev);
-		assert_int_equal(ret, 0);
-	}
-}
-
-struct test_cancel_state {
-	struct test_cancel_job *job1;
-	struct test_cancel_job *job2;
-	struct test_cancel_job *job3;
-	struct test_cancel_job *job4;
-	struct test_cancel_job *job5;
-	struct test_cancel_job *job6;
-};
-
-static void test_cancel_job(void **private_data)
-{
-	struct pthreadpool_tevent_test *t = *private_data;
-	struct tevent_context *ev = t->ev;
-	struct pthreadpool_tevent *pool = t->opool;
-	struct test_cancel_state *state = NULL;
-	int ret;
-	bool ok;
-	int fdpair[2] = { -1, -1 };
-	char c = 0;
-
-	state = talloc_zero(t, struct test_cancel_state);
-	assert_non_null(state);
-	state->job1 = test_cancel_job_create(state);
-	assert_non_null(state->job1);
-	state->job2 = test_cancel_job_create(state);
-	assert_non_null(state->job2);
-	state->job3 = test_cancel_job_create(state);
-	assert_non_null(state->job3);
-
-	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair);
-	assert_int_equal(ret, 0);
-
-	state->job1->fdm = fdpair[0];
-	state->job1->fdj = fdpair[1];
-
-	assert_int_equal(pthreadpool_tevent_queued_jobs(pool), 0);
-
-	will_return(__wrap_pthread_create, 0);
-	state->job1->req = pthreadpool_tevent_job_send(
-		state->job1, ev, pool, test_cancel_job_fn, state->job1);
-	assert_non_null(state->job1->req);
-	tevent_req_set_callback(state->job1->req,
-				test_cancel_job_done,
-				state->job1);
-
-	state->job2->req = pthreadpool_tevent_job_send(
-		state->job2, ev, pool, test_cancel_job_fn, NULL);
-	assert_non_null(state->job2->req);
-	tevent_req_set_callback(state->job2->req,
-				test_cancel_job_done,
-				state->job2);
-
-	state->job3->req = pthreadpool_tevent_job_send(
-		state->job3, ev, pool, test_cancel_job_fn, NULL);
-	assert_non_null(state->job3->req);
-	tevent_req_set_callback(state->job3->req,
-				test_cancel_job_done,
-				state->job3);
-
-	/*
-	 * Wait for the job 1 to start.
-	 */
-	ret = read(state->job1->fdm, &c, 1);
-	assert_int_equal(ret, 1);
-
-	/*
-	 * We cancel job 3 and destroy job2.
-	 * Both should never be executed.
-	 */
-	assert_int_equal(pthreadpool_tevent_queued_jobs(pool), 2);
-	TALLOC_FREE(state->job2->req);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(pool), 1);
-	ok = tevent_req_cancel(state->job3->req);
-	assert_true(ok);
-	assert_int_equal(pthreadpool_tevent_queued_jobs(pool), 0);
-
-	/*
-	 * Job 3 should complete as canceled, while
-	 * job 1 is still running.
-	 */
-	test_cancel_job_wait(state->job3, ev);
-	assert_int_equal(state->job3->ret, ECANCELED);
-	assert_null(state->job3->req);
-	assert_false(state->job3->started);
-
-	/*
-	 * Now job1 is canceled while it's running,
-	 * this should let it stop it's loop.
-	 */
-	ok = tevent_req_cancel(state->job1->req);
-	assert_false(ok);
-
-	/*
-	 * Job 1 completes, It got at least one sleep
-	 * timeout loop and has state->job1->canceled set.
-	 */
-	test_cancel_job_wait(state->job1, ev);
-	assert_int_equal(state->job1->ret, 0);
-	assert_null(state->job1->req);
-	assert_true(state->job1->started);
-	assert_true(state->job1->finished);
-	assert_true(state->job1->canceled);
-	assert_false(state->job1->orphaned);
-	assert_in_range(state->job1->polls, 1, 100);
-	assert_int_equal(state->job1->timeouts, state->job1->polls);
-
-	/*
-	 * Now we create jobs 4 and 5
-	 * Both should execute.
-	 * Job 4 is orphaned while running by a TALLOC_FREE()
-	 * This should stop job 4 and let job 5 start.
-	 * We do a "normal" exit in job 5 by creating some activity
-	 * on the socketpair.
-	 */
-
-	state->job4 = test_cancel_job_create(state);
-	assert_non_null(state->job4);
-
-	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair);
-	assert_int_equal(ret, 0);
-
-	state->job4->fdm = fdpair[0];
-	state->job4->fdj = fdpair[1];
-
-	state->job4->req = pthreadpool_tevent_job_send(
-		state->job4, ev, pool, test_cancel_job_fn, state->job4);
-	assert_non_null(state->job4->req);
-	tevent_req_set_callback(state->job4->req,
-				test_cancel_job_done,
-				state->job4);
-
-	state->job5 = test_cancel_job_create(state);
-	assert_non_null(state->job5);
-
-	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair);
-	assert_int_equal(ret, 0);
-
-	state->job5->fdm = fdpair[0];
-	state->job5->fdj = fdpair[1];
-
-	state->job5->req = pthreadpool_tevent_job_send(
-		state->job5, ev, pool, test_cancel_job_fn, state->job5);
-	assert_non_null(state->job5->req);
-	tevent_req_set_callback(state->job5->req,
-				test_cancel_job_done,
-				state->job5);
-
-	/*
-	 * Make sure job 5 can exit as soon as possible.
-	 * It will never get a sleep/poll timeout.
-	 */
-	ret = write(state->job5->fdm, &c, 1);
-	assert_int_equal(ret, 1);
-
-	/*
-	 * Wait for the job 4 to start
-	 */
-	ret = read(state->job4->fdm, &c, 1);
-	assert_int_equal(ret, 1);
-
-	assert_int_equal(pthreadpool_tevent_queued_jobs(pool), 1);
-
-	/*
-	 * destroy the request so that it's marked
-	 * as orphaned.
-	 */
-	TALLOC_FREE(state->job4->req);
-
-	/*
-	 * Job 5 completes, It got no sleep timeout loop.
-	 */
-	test_cancel_job_wait(state->job5, ev);
-	assert_int_equal(state->job5->ret, 0);
-	assert_null(state->job5->req);
-	assert_true(state->job5->started);
-	assert_true(state->job5->finished);
-	assert_false(state->job5->canceled);
-	assert_false(state->job5->orphaned);
-	assert_int_equal(state->job5->polls, 1);
-	assert_int_equal(state->job5->timeouts, 0);
-
-	assert_int_equal(pthreadpool_tevent_queued_jobs(pool), 0);
-
-	/*
-	 * Job 2 is still not executed as we did a TALLOC_FREE()
-	 * before is was scheduled.
-	 */
-	assert_false(state->job2->completed);
-	assert_false(state->job2->started);
-
-	/*
-	 * Job 4 is still wasn't completed as we did a TALLOC_FREE()
-	 * while it is was running. but it was started and has
-	 * orphaned set
-	 */
-	assert_false(state->job4->completed);
-	assert_true(state->job4->started);
-	assert_true(state->job4->finished);
-	assert_false(state->job4->canceled);
-	assert_true(state->job4->orphaned);
-	assert_in_range(state->job4->polls, 1, 100);
-	assert_int_equal(state->job4->timeouts, state->job4->polls);
-
-	/*
-	 * Now we create jobs 6
-	 * We destroy the pool while it's executing.
-	 */
-
-	state->job6 = test_cancel_job_create(state);
-	assert_non_null(state->job6);
-
-	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair);
-	assert_int_equal(ret, 0);
-
-	state->job6->fdm = fdpair[0];
-	state->job6->fdj = fdpair[1];
-
-	state->job6->req = pthreadpool_tevent_job_send(
-		state->job6, ev, pool, test_cancel_job_fn, state->job6);
-	assert_non_null(state->job6->req);
-	tevent_req_set_callback(state->job6->req,
-				test_cancel_job_done,
-				state->job6);
-
-	/*
-	 * Wait for the job 6 to start
-	 */
-	ret = read(state->job6->fdm, &c, 1);
-	assert_int_equal(ret, 1);
-
-	assert_int_equal(pthreadpool_tevent_queued_jobs(pool), 0);
-
-	/*
-	 * destroy the request so that it's marked
-	 * as orphaned.
-	 */
-	pool = NULL;
-	TALLOC_FREE(t->opool);
-
-	/*
-	 * Wait until the job finished.
-	 */
-	ret = read(state->job6->fdm, &c, 1);
-	assert_int_equal(ret, 0);
-
-	/*
-	 * Job 6 is still dangling arround.
-	 *
-	 * We need to convince valgrind --tool={drd,helgrind}
-	 * that the read above is good enough to be
-	 * sure the job is finished and closed the other end of
-	 * the socketpair.
-	 */
-	ANNOTATE_BENIGN_RACE_SIZED(state->job6,
-				   sizeof(*state->job6),
-				   "protected by thread fence");
-	assert_non_null(state->job6->req);
-	assert_true(tevent_req_is_in_progress(state->job6->req));
-	assert_false(state->job6->completed);
-	assert_true(state->job6->started);
-	assert_true(state->job6->finished);
-	assert_false(state->job6->canceled);
-	assert_true(state->job6->orphaned);
-	assert_in_range(state->job6->polls, 1, 100);
-	assert_int_equal(state->job6->timeouts, state->job4->polls);
-
-	TALLOC_FREE(state);
-}
-
 int main(int argc, char **argv)
 {
 	const struct CMUnitTest tests[] = {
 		cmocka_unit_test_setup_teardown(test_create,
 						setup_pthreadpool_tevent,
 						teardown_pthreadpool_tevent),
-		cmocka_unit_test_setup_teardown(test_cancel_job,
-						setup_pthreadpool_tevent,
-						teardown_pthreadpool_tevent),
 	};
 
 	cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
-- 
2.17.1


From 5fa876d3abb9bded890cf34187efc16f47f7f811 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:44:22 +0100
Subject: [PATCH 24/66] Revert "pthreadpool: add a comment about a further
 optimization in pthreadpool_tevent_job_destructor()"

This reverts commit f23cac39b36b026650e0922c78fe0fd3fe567e35.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool_tevent.c | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c
index 5ccff6231f0b..a0e146b54678 100644
--- a/lib/pthreadpool/pthreadpool_tevent.c
+++ b/lib/pthreadpool/pthreadpool_tevent.c
@@ -492,23 +492,6 @@ static int pthreadpool_tevent_job_destructor(struct pthreadpool_tevent_job *job)
 		TALLOC_FREE(job->im);
 	}
 
-	/*
-	 * TODO?: We could further improve this by adjusting
-	 * tevent_threaded_schedule_immediate_destructor()
-	 * and allow TALLOC_FREE() during its time
-	 * in the main_ev->scheduled_immediates list.
-	 *
-	 * PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-	 * if (state->needs_fence.signaled) {
-	 *       *
-	 *       * The signal function is completed
-	 *       * in future we may be allowed
-	 *       * to call TALLOC_FREE(job->im).
-	 *       *
-	 *      TALLOC_FREE(job->im);
-	 * }
-	 */
-
 	/*
 	 * pthreadpool_tevent_job_orphan() already removed
 	 * it from pool->jobs. And we don't need try
-- 
2.17.1


From 42918c5cce7a65db9e684b0ebb43cee24f037ff9 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:44:32 +0100
Subject: [PATCH 25/66] Revert "pthreadpool: maintain a list of job_states on
 each pthreadpool_tevent_glue"

This reverts commit aa9b64eccfd037941512bad108c4e3946714a502.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool_tevent.c | 102 +++++++--------------------
 1 file changed, 24 insertions(+), 78 deletions(-)

diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c
index a0e146b54678..604763c07330 100644
--- a/lib/pthreadpool/pthreadpool_tevent.c
+++ b/lib/pthreadpool/pthreadpool_tevent.c
@@ -18,7 +18,6 @@
  */
 
 #include "replace.h"
-#include "system/select.h"
 #include "system/threads.h"
 #include "system/filesys.h"
 #include "pthreadpool_tevent.h"
@@ -106,8 +105,6 @@ struct pthreadpool_tevent_glue {
 	struct tevent_threaded_context *tctx;
 	/* Pointer to link object owned by *ev. */
 	struct pthreadpool_tevent_glue_ev_link *ev_link;
-	/* active jobs */
-	struct pthreadpool_tevent_job_state *states;
 };
 
 /*
@@ -131,8 +128,6 @@ struct pthreadpool_tevent {
 };
 
 struct pthreadpool_tevent_job_state {
-	struct pthreadpool_tevent_job_state *prev, *next;
-	struct pthreadpool_tevent_glue *glue;
 	struct tevent_context *ev;
 	struct tevent_req *req;
 	struct pthreadpool_tevent_job *job;
@@ -328,16 +323,6 @@ static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool)
 static int pthreadpool_tevent_glue_destructor(
 	struct pthreadpool_tevent_glue *glue)
 {
-	struct pthreadpool_tevent_job_state *state = NULL;
-	struct pthreadpool_tevent_job_state *nstate = NULL;
-
-	for (state = glue->states; state != NULL; state = nstate) {
-		nstate = state->next;
-
-		/* The job this removes it from the list */
-		pthreadpool_tevent_job_orphan(state->job);
-	}
-
 	if (glue->pool->glue_list != NULL) {
 		DLIST_REMOVE(glue->pool->glue_list, glue);
 	}
@@ -371,11 +356,9 @@ static int pthreadpool_tevent_glue_link_destructor(
 	return 0;
 }
 
-static int pthreadpool_tevent_register_ev(
-				struct pthreadpool_tevent *pool,
-				struct pthreadpool_tevent_job_state *state)
+static int pthreadpool_tevent_register_ev(struct pthreadpool_tevent *pool,
+					  struct tevent_context *ev)
 {
-	struct tevent_context *ev = state->ev;
 	struct pthreadpool_tevent_glue *glue = NULL;
 	struct pthreadpool_tevent_glue_ev_link *ev_link = NULL;
 
@@ -386,9 +369,7 @@ static int pthreadpool_tevent_register_ev(
 	 * pair.
 	 */
 	for (glue = pool->glue_list; glue != NULL; glue = glue->next) {
-		if (glue->ev == state->ev) {
-			state->glue = glue;
-			DLIST_ADD_END(glue->states, state);
+		if (glue->ev == ev) {
 			return 0;
 		}
 	}
@@ -436,9 +417,6 @@ static int pthreadpool_tevent_register_ev(
 	}
 #endif
 
-	state->glue = glue;
-	DLIST_ADD_END(glue->states, state);
-
 	DLIST_ADD(pool->glue_list, glue);
 	return 0;
 }
@@ -454,7 +432,7 @@ static int pthreadpool_tevent_job_destructor(struct pthreadpool_tevent_job *job)
 	/*
 	 * We should never be called with needs_fence.orphaned == false.
 	 * Only pthreadpool_tevent_job_orphan() will call TALLOC_FREE(job)
-	 * after detaching from the request state, glue and pool list.
+	 * after detaching from the request state and pool list.
 	 */
 	if (!job->needs_fence.orphaned) {
 		abort();
@@ -532,42 +510,6 @@ static void pthreadpool_tevent_job_orphan(struct pthreadpool_tevent_job *job)
 		abort();
 	}
 
-	/*
-	 * Once we marked the request as 'orphaned'
-	 * we spin/loop if it's already marked
-	 * as 'finished' (which means that
-	 * pthreadpool_tevent_job_signal() was entered.
-	 * If it saw 'orphaned' it will exit after setting
-	 * 'dropped', otherwise it dereferences
-	 * job->state->glue->{tctx,ev} until it exited
-	 * after setting 'signaled'.
-	 *
-	 * We need to close this potential gab before
-	 * we can set job->state = NULL.
-	 *
-	 * This is some kind of spinlock, but with
-	 * 1 millisecond sleeps in between, in order
-	 * to give the thread more cpu time to finish.
-	 */
-	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-	while (job->needs_fence.finished) {
-		if (job->needs_fence.dropped) {
-			break;
-		}
-		if (job->needs_fence.signaled) {
-			break;
-		}
-		poll(NULL, 0, 1);
-		PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-	}
-
-	/*
-	 * Once the gab is closed, we can remove
-	 * the glue link.
-	 */
-	DLIST_REMOVE(job->state->glue->states, job->state);
-	job->state->glue = NULL;
-
 	/*
 	 * We need to reparent to a long term context.
 	 * And detach from the request state.
@@ -620,10 +562,6 @@ static void pthreadpool_tevent_job_cleanup(struct tevent_req *req,
 		 * The job request is not scheduled in the pool
 		 * yet or anymore.
 		 */
-		if (state->glue != NULL) {
-			DLIST_REMOVE(state->glue->states, state);
-			state->glue = NULL;
-		}
 		return;
 	}
 
@@ -668,7 +606,7 @@ struct tevent_req *pthreadpool_tevent_job_send(
 		return tevent_req_post(req, ev);
 	}
 
-	ret = pthreadpool_tevent_register_ev(pool, state);
+	ret = pthreadpool_tevent_register_ev(pool, ev);
 	if (tevent_req_error(req, ret)) {
 		return tevent_req_post(req, ev);
 	}
@@ -781,6 +719,9 @@ static int pthreadpool_tevent_job_signal(int jobid,
 	struct pthreadpool_tevent_job *job =
 		talloc_get_type_abort(job_private_data,
 		struct pthreadpool_tevent_job);
+	struct pthreadpool_tevent_job_state *state = job->state;
+	struct tevent_threaded_context *tctx = NULL;
+	struct pthreadpool_tevent_glue *g = NULL;
 
 	job->needs_fence.finished = true;
 	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
@@ -791,22 +732,27 @@ static int pthreadpool_tevent_job_signal(int jobid,
 		return 0;
 	}
 
-	/*
-	 * state and state->glue are valid,
-	 * see the job->needs_fence.finished
-	 * "spinlock" loop in
-	 * pthreadpool_tevent_job_orphan()
-	 */
-	if (job->state->glue->tctx != NULL) {
+#ifdef HAVE_PTHREAD
+	for (g = job->pool->glue_list; g != NULL; g = g->next) {
+		if (g->ev == state->ev) {
+			tctx = g->tctx;
+			break;
+		}
+	}
+
+	if (tctx == NULL) {
+		abort();
+	}
+#endif
+
+	if (tctx != NULL) {
 		/* with HAVE_PTHREAD */
-		tevent_threaded_schedule_immediate(job->state->glue->tctx,
-						   job->im,
+		tevent_threaded_schedule_immediate(tctx, job->im,
 						   pthreadpool_tevent_job_done,
 						   job);
 	} else {
 		/* without HAVE_PTHREAD */
-		tevent_schedule_immediate(job->im,
-					  job->state->glue->ev,
+		tevent_schedule_immediate(job->im, state->ev,
 					  pthreadpool_tevent_job_done,
 					  job);
 	}
-- 
2.17.1


From 00e3e39a5529854bed9f380fa6b82ce8ca7d46ed Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:44:49 +0100
Subject: [PATCH 26/66] Revert "pthreadpool: add helgrind magic to
 PTHREAD_TEVENT_JOB_THREAD_FENCE_*()"

This reverts commit 9b73fda926eb8493e80012794483039be66d4e6c.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool_tevent.c | 34 ----------------------------
 1 file changed, 34 deletions(-)

diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c
index 604763c07330..db20ddc15304 100644
--- a/lib/pthreadpool/pthreadpool_tevent.c
+++ b/lib/pthreadpool/pthreadpool_tevent.c
@@ -26,39 +26,8 @@
 #include "lib/util/dlinklist.h"
 #include "lib/util/attr.h"
 
-/*
- * We try to give some hints to helgrind/drd
- *
- * Note ANNOTATE_BENIGN_RACE_SIZED(address, size, describtion)
- * takes an memory address range that ignored by helgrind/drd
- * 'description' is just ignored...
- *
- *
- * Note that ANNOTATE_HAPPENS_*(unique_uintptr)
- * just takes a DWORD/(void *) as unique key
- * for the barrier.
- */
-#ifdef HAVE_VALGRIND_HELGRIND_H
-#include <valgrind/helgrind.h>
-#endif
-#ifndef ANNOTATE_BENIGN_RACE_SIZED
-#define ANNOTATE_BENIGN_RACE_SIZED(address, size, describtion)
-#endif
-#ifndef ANNOTATE_HAPPENS_BEFORE
-#define ANNOTATE_HAPPENS_BEFORE(unique_uintptr)
-#endif
-#ifndef ANNOTATE_HAPPENS_AFTER
-#define ANNOTATE_HAPPENS_AFTER(unique_uintptr)
-#endif
-#ifndef ANNOTATE_HAPPENS_BEFORE_FORGET_ALL
-#define ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(unique_uintptr)
-#endif
-
 #define PTHREAD_TEVENT_JOB_THREAD_FENCE_INIT(__job) do { \
 	_UNUSED_ const struct pthreadpool_tevent_job *__j = __job; \
-	ANNOTATE_BENIGN_RACE_SIZED(&__j->needs_fence, \
-				   sizeof(__j->needs_fence), \
-				   "race by design, protected by fence"); \
 } while(0);
 
 #ifdef WITH_PTHREADPOOL
@@ -80,14 +49,11 @@
 
 #define PTHREAD_TEVENT_JOB_THREAD_FENCE(__job) do { \
 	_UNUSED_ const struct pthreadpool_tevent_job *__j = __job; \
-	ANNOTATE_HAPPENS_BEFORE(&__job->needs_fence); \
 	__PTHREAD_TEVENT_JOB_THREAD_FENCE(memory_order_seq_cst); \
-	ANNOTATE_HAPPENS_AFTER(&__job->needs_fence); \
 } while(0);
 
 #define PTHREAD_TEVENT_JOB_THREAD_FENCE_FINI(__job) do { \
 	_UNUSED_ const struct pthreadpool_tevent_job *__j = __job; \
-	ANNOTATE_HAPPENS_BEFORE_FORGET_ALL(&__job->needs_fence); \
 } while(0);
 
 struct pthreadpool_tevent_job_state;
-- 
2.17.1


From 4e6e5eae7c3260ba747aa2ee818ef18d1e9c9a8c Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Sun, 23 Dec 2018 09:46:13 +0100
Subject: [PATCH 27/66] Revert "pthreadpool: add some lockless coordination
 between the main and job threads"

This reverts commit 9656b8d8ee11ee351870286f16ea8fbe49112292.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool_tevent.c | 212 +--------------------------
 lib/pthreadpool/pthreadpool_tevent.h |  14 --
 wscript                              |  12 +-
 3 files changed, 7 insertions(+), 231 deletions(-)

diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c
index db20ddc15304..3eca605d0c4a 100644
--- a/lib/pthreadpool/pthreadpool_tevent.c
+++ b/lib/pthreadpool/pthreadpool_tevent.c
@@ -18,43 +18,11 @@
  */
 
 #include "replace.h"
-#include "system/threads.h"
 #include "system/filesys.h"
 #include "pthreadpool_tevent.h"
 #include "pthreadpool.h"
 #include "lib/util/tevent_unix.h"
 #include "lib/util/dlinklist.h"
-#include "lib/util/attr.h"
-
-#define PTHREAD_TEVENT_JOB_THREAD_FENCE_INIT(__job) do { \
-	_UNUSED_ const struct pthreadpool_tevent_job *__j = __job; \
-} while(0);
-
-#ifdef WITH_PTHREADPOOL
-/*
- * configure checked we have pthread and atomic_thread_fence() available
- */
-#define __PTHREAD_TEVENT_JOB_THREAD_FENCE(__order) do { \
-	atomic_thread_fence(__order); \
-} while(0)
-#else
-/*
- * we're using lib/pthreadpool/pthreadpool_sync.c ...
- */
-#define __PTHREAD_TEVENT_JOB_THREAD_FENCE(__order) do { } while(0)
-#ifndef HAVE___THREAD
-#define __thread
-#endif
-#endif
-
-#define PTHREAD_TEVENT_JOB_THREAD_FENCE(__job) do { \
-	_UNUSED_ const struct pthreadpool_tevent_job *__j = __job; \
-	__PTHREAD_TEVENT_JOB_THREAD_FENCE(memory_order_seq_cst); \
-} while(0);
-
-#define PTHREAD_TEVENT_JOB_THREAD_FENCE_FINI(__job) do { \
-	_UNUSED_ const struct pthreadpool_tevent_job *__j = __job; \
-} while(0);
 
 struct pthreadpool_tevent_job_state;
 
@@ -108,70 +76,6 @@ struct pthreadpool_tevent_job {
 
 	void (*fn)(void *private_data);
 	void *private_data;
-
-	/*
-	 * Coordination between threads
-	 *
-	 * There're only one side writing each element
-	 * either the main process or the job thread.
-	 *
-	 * The coordination is done by a full memory
-	 * barrier using atomic_thread_fence(memory_order_seq_cst)
-	 * wrapped in PTHREAD_TEVENT_JOB_THREAD_FENCE()
-	 */
-	struct {
-		/*
-		 * 'maycancel'
-		 * set when tevent_req_cancel() is called.
-		 * (only written by main thread!)
-		 */
-		bool maycancel;
-
-		/*
-		 * 'orphaned'
-		 * set when talloc_free is called on the job request,
-		 * tevent_context or pthreadpool_tevent.
-		 * (only written by main thread!)
-		 */
-		bool orphaned;
-
-		/*
-		 * 'started'
-		 * set when the job is picked up by a worker thread
-		 * (only written by job thread!)
-		 */
-		bool started;
-
-		/*
-		 * 'executed'
-		 * set once the job function returned.
-		 * (only written by job thread!)
-		 */
-		bool executed;
-
-		/*
-		 * 'finished'
-		 * set when pthreadpool_tevent_job_signal() is entered
-		 * (only written by job thread!)
-		 */
-		bool finished;
-
-		/*
-		 * 'dropped'
-		 * set when pthreadpool_tevent_job_signal() leaves with
-		 * orphaned already set.
-		 * (only written by job thread!)
-		 */
-		bool dropped;
-
-		/*
-		 * 'signaled'
-		 * set when pthreadpool_tevent_job_signal() leaves normal
-		 * and the immediate event was scheduled.
-		 * (only written by job thread!)
-		 */
-		bool signaled;
-	} needs_fence;
 };
 
 static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool);
@@ -396,11 +300,11 @@ static bool pthreadpool_tevent_job_cancel(struct tevent_req *req);
 static int pthreadpool_tevent_job_destructor(struct pthreadpool_tevent_job *job)
 {
 	/*
-	 * We should never be called with needs_fence.orphaned == false.
+	 * We should never be called with state->state != NULL.
 	 * Only pthreadpool_tevent_job_orphan() will call TALLOC_FREE(job)
 	 * after detaching from the request state and pool list.
 	 */
-	if (!job->needs_fence.orphaned) {
+	if (job->state != NULL) {
 		abort();
 	}
 
@@ -425,17 +329,6 @@ static int pthreadpool_tevent_job_destructor(struct pthreadpool_tevent_job *job)
 		}
 	}
 
-	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-	if (job->needs_fence.dropped) {
-		/*
-		 * The signal function saw job->needs_fence.orphaned
-		 * before it started the signaling via the immediate
-		 * event. So we'll never geht triggered and can
-		 * remove job->im and let the whole job go...
-		 */
-		TALLOC_FREE(job->im);
-	}
-
 	/*
 	 * pthreadpool_tevent_job_orphan() already removed
 	 * it from pool->jobs. And we don't need try
@@ -459,15 +352,11 @@ static int pthreadpool_tevent_job_destructor(struct pthreadpool_tevent_job *job)
 	 */
 	DLIST_REMOVE(orphaned_jobs, job);
 
-	PTHREAD_TEVENT_JOB_THREAD_FENCE_FINI(job);
 	return 0;
 }
 
 static void pthreadpool_tevent_job_orphan(struct pthreadpool_tevent_job *job)
 {
-	job->needs_fence.orphaned = true;
-	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-
 	/*
 	 * We're the only function that sets
 	 * job->state = NULL;
@@ -588,7 +477,6 @@ struct tevent_req *pthreadpool_tevent_job_send(
 	if (tevent_req_nomem(job->im, req)) {
 		return tevent_req_post(req, ev);
 	}
-	PTHREAD_TEVENT_JOB_THREAD_FENCE_INIT(job);
 	talloc_set_destructor(job, pthreadpool_tevent_job_destructor);
 	DLIST_ADD_END(job->pool->jobs, job);
 	job->state = state;
@@ -605,76 +493,13 @@ struct tevent_req *pthreadpool_tevent_job_send(
 	return req;
 }
 
-static __thread struct pthreadpool_tevent_job *current_job;
-
-bool pthreadpool_tevent_current_job_canceled(void)
-{
-	if (current_job == NULL) {
-		/*
-		 * Should only be called from within
-		 * the job function.
-		 */
-		abort();
-		return false;
-	}
-
-	PTHREAD_TEVENT_JOB_THREAD_FENCE(current_job);
-	return current_job->needs_fence.maycancel;
-}
-
-bool pthreadpool_tevent_current_job_orphaned(void)
-{
-	if (current_job == NULL) {
-		/*
-		 * Should only be called from within
-		 * the job function.
-		 */
-		abort();
-		return false;
-	}
-
-	PTHREAD_TEVENT_JOB_THREAD_FENCE(current_job);
-	return current_job->needs_fence.orphaned;
-}
-
-bool pthreadpool_tevent_current_job_continue(void)
-{
-	if (current_job == NULL) {
-		/*
-		 * Should only be called from within
-		 * the job function.
-		 */
-		abort();
-		return false;
-	}
-
-	PTHREAD_TEVENT_JOB_THREAD_FENCE(current_job);
-	if (current_job->needs_fence.maycancel) {
-		return false;
-	}
-	PTHREAD_TEVENT_JOB_THREAD_FENCE(current_job);
-	if (current_job->needs_fence.orphaned) {
-		return false;
-	}
-
-	return true;
-}
-
 static void pthreadpool_tevent_job_fn(void *private_data)
 {
 	struct pthreadpool_tevent_job *job =
 		talloc_get_type_abort(private_data,
 		struct pthreadpool_tevent_job);
 
-	current_job = job;
-	job->needs_fence.started = true;
-	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-
 	job->fn(job->private_data);
-
-	job->needs_fence.executed = true;
-	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-	current_job = NULL;
 }
 
 static int pthreadpool_tevent_job_signal(int jobid,
@@ -689,12 +514,8 @@ static int pthreadpool_tevent_job_signal(int jobid,
 	struct tevent_threaded_context *tctx = NULL;
 	struct pthreadpool_tevent_glue *g = NULL;
 
-	job->needs_fence.finished = true;
-	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-	if (job->needs_fence.orphaned) {
+	if (state == NULL) {
 		/* Request already gone */
-		job->needs_fence.dropped = true;
-		PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
 		return 0;
 	}
 
@@ -723,8 +544,6 @@ static int pthreadpool_tevent_job_signal(int jobid,
 					  job);
 	}
 
-	job->needs_fence.signaled = true;
-	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
 	return 0;
 }
 
@@ -747,17 +566,9 @@ static void pthreadpool_tevent_job_done(struct tevent_context *ctx,
 
 	/*
 	 * pthreadpool_tevent_job_cleanup()
-	 * (called by tevent_req_done() or
-	 * tevent_req_error()) will destroy the job.
+	 * will destroy the job.
 	 */
-
-	if (job->needs_fence.executed) {
-		tevent_req_done(state->req);
-		return;
-	}
-
-	tevent_req_error(state->req, ENOEXEC);
-	return;
+	tevent_req_done(state->req);
 }
 
 static bool pthreadpool_tevent_job_cancel(struct tevent_req *req)
@@ -772,19 +583,6 @@ static bool pthreadpool_tevent_job_cancel(struct tevent_req *req)
 		return false;
 	}
 
-	job->needs_fence.maycancel = true;
-	PTHREAD_TEVENT_JOB_THREAD_FENCE(job);
-	if (job->needs_fence.started) {
-		/*
-		 * It was too late to cancel the request.
-		 *
-		 * The job still has the chance to look
-		 * at pthreadpool_tevent_current_job_canceled()
-		 * or pthreadpool_tevent_current_job_continue()
-		 */
-		return false;
-	}
-
 	num = pthreadpool_cancel_job(job->pool->pool, 0,
 				     pthreadpool_tevent_job_fn,
 				     job);
diff --git a/lib/pthreadpool/pthreadpool_tevent.h b/lib/pthreadpool/pthreadpool_tevent.h
index 37e491e17c47..fdb86e23757a 100644
--- a/lib/pthreadpool/pthreadpool_tevent.h
+++ b/lib/pthreadpool/pthreadpool_tevent.h
@@ -32,20 +32,6 @@ int pthreadpool_tevent_init(TALLOC_CTX *mem_ctx, unsigned max_threads,
 size_t pthreadpool_tevent_max_threads(struct pthreadpool_tevent *pool);
 size_t pthreadpool_tevent_queued_jobs(struct pthreadpool_tevent *pool);
 
-/*
- * return true - if tevent_req_cancel() was called.
- */
-bool pthreadpool_tevent_current_job_canceled(void);
-/*
- * return true - if talloc_free() was called on the job request,
- * tevent_context or pthreadpool_tevent.
- */
-bool pthreadpool_tevent_current_job_orphaned(void);
-/*
- * return true if canceled and orphaned are both false.
- */
-bool pthreadpool_tevent_current_job_continue(void);
-
 struct tevent_req *pthreadpool_tevent_job_send(
 	TALLOC_CTX *mem_ctx, struct tevent_context *ev,
 	struct pthreadpool_tevent *pool,
diff --git a/wscript b/wscript
index da4254efde49..e38a8e9aecfd 100644
--- a/wscript
+++ b/wscript
@@ -279,18 +279,10 @@ def configure(conf):
         conf.DEFINE('WITH_NTVFS_FILESERVER', 1)
 
     if Options.options.with_pthreadpool:
-        if conf.CONFIG_SET('HAVE_PTHREAD') and \
-           conf.CONFIG_SET('HAVE___THREAD') and \
-           conf.CONFIG_SET('HAVE_ATOMIC_THREAD_FENCE_SUPPORT'):
+        if conf.CONFIG_SET('HAVE_PTHREAD'):
             conf.DEFINE('WITH_PTHREADPOOL', '1')
         else:
-            if not conf.CONFIG_SET('HAVE_PTHREAD'):
-                Logs.warn("pthreadpool support cannot be enabled when pthread support was not found")
-            if not conf.CONFIG_SET('HAVE_ATOMIC_THREAD_FENCE_SUPPORT'):
-                Logs.warn("""pthreadpool support cannot be enabled when there is
-                          no support for atomic_thead_fence()""")
-            if not conf.CONFIG_SET('HAVE___THREAD'):
-                Logs.warn("pthreadpool support cannot be enabled when __thread support was not found")
+            Logs.warn("pthreadpool support cannot be enabled when pthread support was not found")
             conf.undefine('WITH_PTHREADPOOL')
 
     conf.SET_TARGET_TYPE('jansson', 'EMPTY')
-- 
2.17.1


From 7f29439bf4f0fa51a638d5a5c476e98733bc16fe Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 28 Dec 2018 09:02:54 +0100
Subject: [PATCH 28/66] Revert "pthreadpool: maintain a global list of orphaned
 pthreadpool_tevent_jobs"

This reverts commit 25756425aaf5465e56ea809cd415b6a387848919.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool_tevent.c | 41 ----------------------------
 lib/pthreadpool/pthreadpool_tevent.h |  2 --
 2 files changed, 43 deletions(-)

diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c
index 3eca605d0c4a..7fc49ce671e3 100644
--- a/lib/pthreadpool/pthreadpool_tevent.c
+++ b/lib/pthreadpool/pthreadpool_tevent.c
@@ -82,24 +82,6 @@ static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool);
 
 static void pthreadpool_tevent_job_orphan(struct pthreadpool_tevent_job *job);
 
-static struct pthreadpool_tevent_job *orphaned_jobs;
-
-void pthreadpool_tevent_cleanup_orphaned_jobs(void)
-{
-	struct pthreadpool_tevent_job *job = NULL;
-	struct pthreadpool_tevent_job *njob = NULL;
-
-	for (job = orphaned_jobs; job != NULL; job = njob) {
-		njob = job->next;
-
-		/*
-		 * The job destructor keeps the job alive
-		 * (and in the list) or removes it from the list.
-		 */
-		TALLOC_FREE(job);
-	}
-}
-
 static int pthreadpool_tevent_job_signal(int jobid,
 					 void (*job_fn)(void *private_data),
 					 void *job_private_data,
@@ -111,8 +93,6 @@ int pthreadpool_tevent_init(TALLOC_CTX *mem_ctx, unsigned max_threads,
 	struct pthreadpool_tevent *pool;
 	int ret;
 
-	pthreadpool_tevent_cleanup_orphaned_jobs();
-
 	pool = talloc_zero(mem_ctx, struct pthreadpool_tevent);
 	if (pool == NULL) {
 		return ENOMEM;
@@ -185,8 +165,6 @@ static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool)
 	}
 	pool->pool = NULL;
 
-	pthreadpool_tevent_cleanup_orphaned_jobs();
-
 	return 0;
 }
 
@@ -340,18 +318,10 @@ static int pthreadpool_tevent_job_destructor(struct pthreadpool_tevent_job *job)
 		/*
 		 * state->im still there means, we need to wait for the
 		 * immediate event to be triggered or just leak the memory.
-		 *
-		 * Move it to the orphaned list, if it's not already there.
 		 */
 		return -1;
 	}
 
-	/*
-	 * Finally remove from the orphaned_jobs list
-	 * and let talloc destroy us.
-	 */
-	DLIST_REMOVE(orphaned_jobs, job);
-
 	return 0;
 }
 
@@ -393,15 +363,6 @@ static void pthreadpool_tevent_job_orphan(struct pthreadpool_tevent_job *job)
 	 */
 	DLIST_REMOVE(job->pool->jobs, job);
 
-	/*
-	 * Add it to the list of orphaned jobs,
-	 * which may be cleaned up later.
-	 *
-	 * The destructor removes it from the list
-	 * when possible or it denies the free
-	 * and keep it in the list.
-	 */
-	DLIST_ADD_END(orphaned_jobs, job);
 	TALLOC_FREE(job);
 }
 
@@ -440,8 +401,6 @@ struct tevent_req *pthreadpool_tevent_job_send(
 	struct pthreadpool_tevent_job *job = NULL;
 	int ret;
 
-	pthreadpool_tevent_cleanup_orphaned_jobs();
-
 	req = tevent_req_create(mem_ctx, &state,
 				struct pthreadpool_tevent_job_state);
 	if (req == NULL) {
diff --git a/lib/pthreadpool/pthreadpool_tevent.h b/lib/pthreadpool/pthreadpool_tevent.h
index fdb86e23757a..10d3a71c40a7 100644
--- a/lib/pthreadpool/pthreadpool_tevent.h
+++ b/lib/pthreadpool/pthreadpool_tevent.h
@@ -22,8 +22,6 @@
 
 #include <tevent.h>
 
-void pthreadpool_tevent_cleanup_orphaned_jobs(void);
-
 struct pthreadpool_tevent;
 
 int pthreadpool_tevent_init(TALLOC_CTX *mem_ctx, unsigned max_threads,
-- 
2.17.1


From 1bdef30e7e103876c359721f425083710b9b6bf8 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 28 Dec 2018 09:03:34 +0100
Subject: [PATCH 29/66] Revert "pthreadpool: add
 pthreadpool_tevent_job_cancel()"

This reverts commit 791c05144ee9296024cc0fdebe4afeaaf67e26bc.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool_tevent.c | 40 ----------------------------
 1 file changed, 40 deletions(-)

diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c
index 7fc49ce671e3..6999730f2550 100644
--- a/lib/pthreadpool/pthreadpool_tevent.c
+++ b/lib/pthreadpool/pthreadpool_tevent.c
@@ -273,7 +273,6 @@ static void pthreadpool_tevent_job_fn(void *private_data);
 static void pthreadpool_tevent_job_done(struct tevent_context *ctx,
 					struct tevent_immediate *im,
 					void *private_data);
-static bool pthreadpool_tevent_job_cancel(struct tevent_req *req);
 
 static int pthreadpool_tevent_job_destructor(struct pthreadpool_tevent_job *job)
 {
@@ -448,7 +447,6 @@ struct tevent_req *pthreadpool_tevent_job_send(
 		return tevent_req_post(req, ev);
 	}
 
-	tevent_req_set_cancel_fn(req, pthreadpool_tevent_job_cancel);
 	return req;
 }
 
@@ -530,44 +528,6 @@ static void pthreadpool_tevent_job_done(struct tevent_context *ctx,
 	tevent_req_done(state->req);
 }
 
-static bool pthreadpool_tevent_job_cancel(struct tevent_req *req)
-{
-	struct pthreadpool_tevent_job_state *state =
-		tevent_req_data(req,
-		struct pthreadpool_tevent_job_state);
-	struct pthreadpool_tevent_job *job = state->job;
-	size_t num;
-
-	if (job == NULL) {
-		return false;
-	}
-
-	num = pthreadpool_cancel_job(job->pool->pool, 0,
-				     pthreadpool_tevent_job_fn,
-				     job);
-	if (num == 0) {
-		/*
-		 * It was too late to cancel the request.
-		 */
-		return false;
-	}
-
-	/*
-	 * It was not too late to cancel the request.
-	 *
-	 * We can remove job->im, as it will never be used.
-	 */
-	TALLOC_FREE(job->im);
-
-	/*
-	 * pthreadpool_tevent_job_cleanup()
-	 * will destroy the job.
-	 */
-	tevent_req_defer_callback(req, state->ev);
-	tevent_req_error(req, ECANCELED);
-	return true;
-}
-
 int pthreadpool_tevent_job_recv(struct tevent_req *req)
 {
 	return tevent_req_simple_recv_unix(req);
-- 
2.17.1


From 2437cba0c25f81ee4a66fbcb9bf760647ee23669 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 28 Dec 2018 09:03:45 +0100
Subject: [PATCH 30/66] Revert "pthreadpool: split out pthreadpool_tevent_job
 from pthreadpool_tevent_job_state"

This reverts commit 245d684d28dab630f3d47ff61006a1fe3e5eeefa.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 lib/pthreadpool/pthreadpool_tevent.c | 238 ++++++++-------------------
 1 file changed, 66 insertions(+), 172 deletions(-)

diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c
index 6999730f2550..389bb06b54c1 100644
--- a/lib/pthreadpool/pthreadpool_tevent.c
+++ b/lib/pthreadpool/pthreadpool_tevent.c
@@ -58,21 +58,15 @@ struct pthreadpool_tevent {
 	struct pthreadpool *pool;
 	struct pthreadpool_tevent_glue *glue_list;
 
-	struct pthreadpool_tevent_job *jobs;
+	struct pthreadpool_tevent_job_state *jobs;
 };
 
 struct pthreadpool_tevent_job_state {
-	struct tevent_context *ev;
-	struct tevent_req *req;
-	struct pthreadpool_tevent_job *job;
-};
-
-struct pthreadpool_tevent_job {
-	struct pthreadpool_tevent_job *prev, *next;
-
+	struct pthreadpool_tevent_job_state *prev, *next;
 	struct pthreadpool_tevent *pool;
-	struct pthreadpool_tevent_job_state *state;
+	struct tevent_context *ev;
 	struct tevent_immediate *im;
+	struct tevent_req *req;
 
 	void (*fn)(void *private_data);
 	void *private_data;
@@ -80,8 +74,6 @@ struct pthreadpool_tevent_job {
 
 static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool);
 
-static void pthreadpool_tevent_job_orphan(struct pthreadpool_tevent_job *job);
-
 static int pthreadpool_tevent_job_signal(int jobid,
 					 void (*job_fn)(void *private_data),
 					 void *job_private_data,
@@ -131,8 +123,7 @@ size_t pthreadpool_tevent_queued_jobs(struct pthreadpool_tevent *pool)
 
 static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool)
 {
-	struct pthreadpool_tevent_job *job = NULL;
-	struct pthreadpool_tevent_job *njob = NULL;
+	struct pthreadpool_tevent_job_state *state, *next;
 	struct pthreadpool_tevent_glue *glue = NULL;
 	int ret;
 
@@ -141,11 +132,10 @@ static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool)
 		return ret;
 	}
 
-	for (job = pool->jobs; job != NULL; job = njob) {
-		njob = job->next;
-
-		/* The job this removes it from the list */
-		pthreadpool_tevent_job_orphan(job);
+	for (state = pool->jobs; state != NULL; state = next) {
+		next = state->next;
+		DLIST_REMOVE(pool->jobs, state);
+		state->pool = NULL;
 	}
 
 	/*
@@ -274,120 +264,27 @@ static void pthreadpool_tevent_job_done(struct tevent_context *ctx,
 					struct tevent_immediate *im,
 					void *private_data);
 
-static int pthreadpool_tevent_job_destructor(struct pthreadpool_tevent_job *job)
+static int pthreadpool_tevent_job_state_destructor(
+	struct pthreadpool_tevent_job_state *state)
 {
-	/*
-	 * We should never be called with state->state != NULL.
-	 * Only pthreadpool_tevent_job_orphan() will call TALLOC_FREE(job)
-	 * after detaching from the request state and pool list.
-	 */
-	if (job->state != NULL) {
-		abort();
-	}
-
-	/*
-	 * If the job is not finished (job->im still there)
-	 * and it's still attached to the pool,
-	 * we try to cancel it (before it was starts)
-	 */
-	if (job->im != NULL && job->pool != NULL) {
-		size_t num;
-
-		num = pthreadpool_cancel_job(job->pool->pool, 0,
-					     pthreadpool_tevent_job_fn,
-					     job);
-		if (num != 0) {
-			/*
-			 * It was not too late to cancel the request.
-			 *
-			 * We can remove job->im, as it will never be used.
-			 */
-			TALLOC_FREE(job->im);
-		}
-	}
-
-	/*
-	 * pthreadpool_tevent_job_orphan() already removed
-	 * it from pool->jobs. And we don't need try
-	 * pthreadpool_cancel_job() again.
-	 */
-	job->pool = NULL;
-
-	if (job->im != NULL) {
-		/*
-		 * state->im still there means, we need to wait for the
-		 * immediate event to be triggered or just leak the memory.
-		 */
-		return -1;
-	}
-
-	return 0;
-}
-
-static void pthreadpool_tevent_job_orphan(struct pthreadpool_tevent_job *job)
-{
-	/*
-	 * We're the only function that sets
-	 * job->state = NULL;
-	 */
-	if (job->state == NULL) {
-		abort();
+	if (state->pool == NULL) {
+		return 0;
 	}
 
 	/*
-	 * We need to reparent to a long term context.
-	 * And detach from the request state.
-	 * Maybe the destructor will keep the memory
-	 * and leak it for now.
+	 * We should never be called with state->req == NULL,
+	 * state->pool must be cleared before the 2nd talloc_free().
 	 */
-	(void)talloc_reparent(job->state, NULL, job);
-	job->state->job = NULL;
-	job->state = NULL;
-
-	/*
-	 * job->pool will only be set to NULL
-	 * in the first destructur run.
-	 */
-	if (job->pool == NULL) {
+	if (state->req == NULL) {
 		abort();
 	}
 
-	/*
-	 * Dettach it from the pool.
-	 *
-	 * The job might still be running,
-	 * so we keep job->pool.
-	 * The destructor will set it to NULL
-	 * after trying pthreadpool_cancel_job()
-	 */
-	DLIST_REMOVE(job->pool->jobs, job);
-
-	TALLOC_FREE(job);
-}
-
-static void pthreadpool_tevent_job_cleanup(struct tevent_req *req,
-					   enum tevent_req_state req_state)
-{
-	struct pthreadpool_tevent_job_state *state =
-		tevent_req_data(req,
-		struct pthreadpool_tevent_job_state);
-
-	if (state->job == NULL) {
-		/*
-		 * The job request is not scheduled in the pool
-		 * yet or anymore.
-		 */
-		return;
-	}
-
 	/*
 	 * We need to reparent to a long term context.
-	 * Maybe the destructor will keep the memory
-	 * and leak it for now.
 	 */
-	pthreadpool_tevent_job_orphan(state->job);
-	state->job = NULL; /* not needed but looks better */
-	return;
+	(void)talloc_reparent(state->req, NULL, state);
+	state->req = NULL;
+	return -1;
 }
 
 struct tevent_req *pthreadpool_tevent_job_send(
@@ -395,9 +292,8 @@ struct tevent_req *pthreadpool_tevent_job_send(
 	struct pthreadpool_tevent *pool,
 	void (*fn)(void *private_data), void *private_data)
 {
-	struct tevent_req *req = NULL;
-	struct pthreadpool_tevent_job_state *state = NULL;
-	struct pthreadpool_tevent_job *job = NULL;
+	struct tevent_req *req;
+	struct pthreadpool_tevent_job_state *state;
 	int ret;
 
 	req = tevent_req_create(mem_ctx, &state,
@@ -405,10 +301,11 @@ struct tevent_req *pthreadpool_tevent_job_send(
 	if (req == NULL) {
 		return NULL;
 	}
+	state->pool = pool;
 	state->ev = ev;
 	state->req = req;
-
-	tevent_req_set_cleanup_fn(req, pthreadpool_tevent_job_cleanup);
+	state->fn = fn;
+	state->private_data = private_data;
 
 	if (pool == NULL) {
 		tevent_req_error(req, EINVAL);
@@ -419,44 +316,39 @@ struct tevent_req *pthreadpool_tevent_job_send(
 		return tevent_req_post(req, ev);
 	}
 
-	ret = pthreadpool_tevent_register_ev(pool, ev);
-	if (tevent_req_error(req, ret)) {
+	state->im = tevent_create_immediate(state);
+	if (tevent_req_nomem(state->im, req)) {
 		return tevent_req_post(req, ev);
 	}
 
-	job = talloc_zero(state, struct pthreadpool_tevent_job);
-	if (tevent_req_nomem(job, req)) {
-		return tevent_req_post(req, ev);
-	}
-	job->pool = pool;
-	job->fn = fn;
-	job->private_data = private_data;
-	job->im = tevent_create_immediate(state->job);
-	if (tevent_req_nomem(job->im, req)) {
+	ret = pthreadpool_tevent_register_ev(pool, ev);
+	if (tevent_req_error(req, ret)) {
 		return tevent_req_post(req, ev);
 	}
-	talloc_set_destructor(job, pthreadpool_tevent_job_destructor);
-	DLIST_ADD_END(job->pool->jobs, job);
-	job->state = state;
-	state->job = job;
 
-	ret = pthreadpool_add_job(job->pool->pool, 0,
+	ret = pthreadpool_add_job(pool->pool, 0,
 				  pthreadpool_tevent_job_fn,
-				  job);
+				  state);
 	if (tevent_req_error(req, ret)) {
 		return tevent_req_post(req, ev);
 	}
 
+	/*
+	 * Once the job is scheduled, we need to protect
+	 * our memory.
+	 */
+	talloc_set_destructor(state, pthreadpool_tevent_job_state_destructor);
+
+	DLIST_ADD_END(pool->jobs, state);
+
 	return req;
 }
 
 static void pthreadpool_tevent_job_fn(void *private_data)
 {
-	struct pthreadpool_tevent_job *job =
-		talloc_get_type_abort(private_data,
-		struct pthreadpool_tevent_job);
-
-	job->fn(job->private_data);
+	struct pthreadpool_tevent_job_state *state = talloc_get_type_abort(
+		private_data, struct pthreadpool_tevent_job_state);
+	state->fn(state->private_data);
 }
 
 static int pthreadpool_tevent_job_signal(int jobid,
@@ -464,20 +356,18 @@ static int pthreadpool_tevent_job_signal(int jobid,
 					 void *job_private_data,
 					 void *private_data)
 {
-	struct pthreadpool_tevent_job *job =
-		talloc_get_type_abort(job_private_data,
-		struct pthreadpool_tevent_job);
-	struct pthreadpool_tevent_job_state *state = job->state;
+	struct pthreadpool_tevent_job_state *state = talloc_get_type_abort(
+		job_private_data, struct pthreadpool_tevent_job_state);
 	struct tevent_threaded_context *tctx = NULL;
 	struct pthreadpool_tevent_glue *g = NULL;
 
-	if (state == NULL) {
-		/* Request already gone */
+	if (state->pool == NULL) {
+		/* The pthreadpool_tevent is already gone */
 		return 0;
 	}
 
 #ifdef HAVE_PTHREAD
-	for (g = job->pool->glue_list; g != NULL; g = g->next) {
+	for (g = state->pool->glue_list; g != NULL; g = g->next) {
 		if (g->ev == state->ev) {
 			tctx = g->tctx;
 			break;
@@ -491,14 +381,14 @@ static int pthreadpool_tevent_job_signal(int jobid,
 
 	if (tctx != NULL) {
 		/* with HAVE_PTHREAD */
-		tevent_threaded_schedule_immediate(tctx, job->im,
+		tevent_threaded_schedule_immediate(tctx, state->im,
 						   pthreadpool_tevent_job_done,
-						   job);
+						   state);
 	} else {
 		/* without HAVE_PTHREAD */
-		tevent_schedule_immediate(job->im, state->ev,
+		tevent_schedule_immediate(state->im, state->ev,
 					  pthreadpool_tevent_job_done,
-					  job);
+					  state);
 	}
 
 	return 0;
@@ -508,23 +398,27 @@ static void pthreadpool_tevent_job_done(struct tevent_context *ctx,
 					struct tevent_immediate *im,
 					void *private_data)
 {
-	struct pthreadpool_tevent_job *job =
-		talloc_get_type_abort(private_data,
-		struct pthreadpool_tevent_job);
-	struct pthreadpool_tevent_job_state *state = job->state;
+	struct pthreadpool_tevent_job_state *state = talloc_get_type_abort(
+		private_data, struct pthreadpool_tevent_job_state);
 
-	TALLOC_FREE(job->im);
+	if (state->pool != NULL) {
+		DLIST_REMOVE(state->pool->jobs, state);
+		state->pool = NULL;
+	}
 
-	if (state == NULL) {
-		/* Request already gone */
-		TALLOC_FREE(job);
+	if (state->req == NULL) {
+		/*
+		 * There was a talloc_free() state->req
+		 * while the job was pending,
+		 * which mean we're reparented on a longterm
+		 * talloc context.
+		 *
+		 * We just cleanup here...
+		 */
+		talloc_free(state);
 		return;
 	}
 
-	/*
-	 * pthreadpool_tevent_job_cleanup()
-	 * will destroy the job.
-	 */
 	tevent_req_done(state->req);
 }
 
-- 
2.17.1


From 57dd07115ec463249de4be820c44170deaea3bc3 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 11:36:43 +0100
Subject: [PATCH 31/66] Revert "smbd: remove unused change_to_root_user() from
 brl_timeout_fn()"

This reverts commit c310647e560abc2343ef2ff0ab15daab0fba2650.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/blocking.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c
index 095c9edeacc0..c281aae619de 100644
--- a/source3/smbd/blocking.c
+++ b/source3/smbd/blocking.c
@@ -47,6 +47,9 @@ void brl_timeout_fn(struct tevent_context *event_ctx,
 		TALLOC_FREE(sconn->smb1.locks.brl_timeout);
 	}
 
+	change_to_root_user();	/* TODO: Possibly run all timed events as
+				 * root */
+
 	process_blocking_lock_queue(sconn);
 }
 
-- 
2.17.1


From 9ea70cb0f6221b3523834d3c8b8fb51117e768ab Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 11:37:03 +0100
Subject: [PATCH 32/66] Revert "smbd: remove unused change_to_root_user() from
 smbd_sig_hup_handler()"

This reverts commit d0b1f96f086bdd613644f64b3f75ee8c4388f674.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/process.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 0a4106257f58..dc95af17393b 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -998,6 +998,7 @@ static void smbd_sig_hup_handler(struct tevent_context *ev,
 		talloc_get_type_abort(private_data,
 		struct smbd_server_connection);
 
+	change_to_root_user();
 	DEBUG(1,("Reloading services after SIGHUP\n"));
 	reload_services(sconn, conn_snum_used, false);
 }
-- 
2.17.1


From 694f41636f1723254c80670556fac50fc0e71cea Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 11:37:16 +0100
Subject: [PATCH 33/66] Revert "smbd: avoid explicit change_to_user() in
 defer_rename_done() already done by impersonation"

This reverts commit e37e41b3cac52e3623f0c79f83733a51edb35c10.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/smb2_setinfo.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c
index 11b126aa7947..7c1f84bd79de 100644
--- a/source3/smbd/smb2_setinfo.c
+++ b/source3/smbd/smb2_setinfo.c
@@ -284,6 +284,7 @@ static void defer_rename_done(struct tevent_req *subreq)
 	NTSTATUS status;
 	struct share_mode_lock *lck;
 	int ret_size = 0;
+	bool ok;
 
 	status = dbwrap_watched_watch_recv(subreq, NULL, NULL);
 	TALLOC_FREE(subreq);
@@ -294,6 +295,16 @@ static void defer_rename_done(struct tevent_req *subreq)
 		return;
 	}
 
+	/*
+	 * Make sure we run as the user again
+	 */
+	ok = change_to_user(state->smb2req->tcon->compat,
+			    state->smb2req->session->compat->vuid);
+	if (!ok) {
+		tevent_req_nterror(state->req, NT_STATUS_ACCESS_DENIED);
+		return;
+	}
+
 	/* Do we still need to wait ? */
 	lck = get_existing_share_mode_lock(state->req, state->fsp->file_id);
 	if (lck == NULL) {
-- 
2.17.1


From 403c53a1ebe495e9c0a704e47f173ff319d27085 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 11:38:27 +0100
Subject: [PATCH 34/66] Revert "smbd: implement
 smbd_impersonate_{conn_vuid,conn_sess,root,guest}_create() wrappers"

This reverts commit 1b804f7ae23f54a6c1004e5ff17b9df1376b5adb.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/uid.c | 951 +--------------------------------------------
 1 file changed, 21 insertions(+), 930 deletions(-)

diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index 0518e5254a8e..e7f0a8f620b8 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -975,961 +975,52 @@ uint64_t get_current_vuid(connection_struct *conn)
 	return current_user.vuid;
 }
 
-struct smbd_impersonate_conn_vuid_state {
-	struct connection_struct *conn;
-	uint64_t vuid;
-};
-
-static bool smbd_impersonate_conn_vuid_before_use(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		const char *location)
-{
-	struct smbd_impersonate_conn_vuid_state *state =
-		talloc_get_type_abort(private_data,
-		struct smbd_impersonate_conn_vuid_state);
-	bool ok;
-
-	DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
-		  "old uid[%ju] old gid[%ju] vuid[%ju] cwd[%s]\n",
-		  __func__, wrap_ev, main_ev, location,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  (uintmax_t)state->vuid, state->conn->cwd_fname->base_name));
-
-	ok = become_user(state->conn, state->vuid);
-	if (!ok) {
-		smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
-		return false;
-	}
-
-	DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
-		  __func__, state->conn->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name));
-
-	return true;
-}
-
-static void smbd_impersonate_conn_vuid_after_use(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		const char *location)
-{
-	struct smbd_impersonate_conn_vuid_state *state =
-		talloc_get_type_abort(private_data,
-		struct smbd_impersonate_conn_vuid_state);
-	bool ok;
-
-	DEBUG(11,("%s: deimpersonating[%s] uid[%ju] gid[%ju] cwd[%s] "
-		  "location[%s]\n",
-		  __func__, state->conn->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name, location));
-
-	ok = unbecome_user();
-	if (!ok) {
-		smb_panic("smbd_impersonate_conn_vuid_after_use() - failed");
-		return;
-	}
-
-	DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
-		  __func__, state->conn->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name));
-}
-
-static void smbd_impersonate_conn_vuid_before_fd_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_fd *fde,
-		uint16_t flags,
-		const char *handler_name,
-		const char *location)
-{
-	struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
-		private_data, struct smbd_impersonate_conn_vuid_state);
-	bool ok;
-
-	DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
-		  __func__, fde, (uintmax_t)flags, handler_name, location));
-
-	ok = change_to_user(state->conn, state->vuid);
-	if (!ok) {
-		smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
-		return;
-	}
-
-	DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
-		  __func__, state->conn->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name));
-}
-
-static void smbd_impersonate_conn_vuid_after_fd_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_fd *fde,
-		uint16_t flags,
-		const char *handler_name,
-		const char *location)
-{
-	DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
-		  __func__, fde, handler_name, location));
-
-	/* be lazy and defer change_to_root_user() */
-}
-
-static void smbd_impersonate_conn_vuid_before_timer_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_timer *te,
-		struct timeval requested_time,
-		struct timeval trigger_time,
-		const char *handler_name,
-		const char *location)
-{
-	struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
-		private_data, struct smbd_impersonate_conn_vuid_state);
-	struct timeval_buf requested_buf;
-	struct timeval_buf trigger_buf;
-	bool ok;
-
-	DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
-		  "handler_name[%s] location[%s]\n",
-		  __func__, te,
-		  timeval_str_buf(&requested_time, true, true, &requested_buf),
-		  timeval_str_buf(&trigger_time, true, true, &trigger_buf),
-		  handler_name, location));
-
-	ok = change_to_user(state->conn, state->vuid);
-	if (!ok) {
-		smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
-		return;
-	}
-
-	DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
-		  __func__, state->conn->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name));
-}
-
-static void smbd_impersonate_conn_vuid_after_timer_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_timer *te,
-		struct timeval requested_time,
-		struct timeval trigger_time,
-		const char *handler_name,
-		const char *location)
-{
-	DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
-		  __func__, te, handler_name, location));
-
-	/* be lazy and defer change_to_root_user() */
-}
-
-static void smbd_impersonate_conn_vuid_before_immediate_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_immediate *im,
-		const char *handler_name,
-		const char *location)
-{
-	struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
-		private_data, struct smbd_impersonate_conn_vuid_state);
-	bool ok;
-
-	DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
-		  __func__, im, handler_name, location));
-
-	ok = change_to_user(state->conn, state->vuid);
-	if (!ok) {
-		smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
-		return;
-	}
-
-	DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
-		  __func__, state->conn->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name));
-}
-
-static void smbd_impersonate_conn_vuid_after_immediate_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_immediate *im,
-		const char *handler_name,
-		const char *location)
-{
-	DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
-		  __func__, im, handler_name, location));
-
-	/* be lazy and defer unbecome_user() */
-}
-
-static void smbd_impersonate_conn_vuid_before_signal_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_signal *se,
-		int signum,
-		int count,
-		void *siginfo,
-		const char *handler_name,
-		const char *location)
-{
-	struct smbd_impersonate_conn_vuid_state *state = talloc_get_type_abort(
-		private_data, struct smbd_impersonate_conn_vuid_state);
-	bool ok;
-
-	DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
-		  "handler_name[%s] location[%s]\n",
-		  __func__, se, signum, count, siginfo, handler_name, location));
-
-	ok = change_to_user(state->conn, state->vuid);
-	if (!ok) {
-		smb_panic("smbd_impersonate_conn_vuid_before_use() - failed");
-		return;
-	}
-
-	DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
-		  __func__, state->conn->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name));
-}
-
-static void smbd_impersonate_conn_vuid_after_signal_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_signal *se,
-		int signum,
-		int count,
-		void *siginfo,
-		const char *handler_name,
-		const char *location)
-{
-	DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
-		  __func__, se, handler_name, location));
-
-	/* be lazy and defer change_to_root_user() */
-}
-
-static const struct tevent_wrapper_ops smbd_impersonate_conn_vuid_ops = {
-	.name				= "smbd_impersonate_conn_vuid",
-	.before_use			= smbd_impersonate_conn_vuid_before_use,
-	.after_use			= smbd_impersonate_conn_vuid_after_use,
-	.before_fd_handler		= smbd_impersonate_conn_vuid_before_fd_handler,
-	.after_fd_handler		= smbd_impersonate_conn_vuid_after_fd_handler,
-	.before_timer_handler		= smbd_impersonate_conn_vuid_before_timer_handler,
-	.after_timer_handler		= smbd_impersonate_conn_vuid_after_timer_handler,
-	.before_immediate_handler	= smbd_impersonate_conn_vuid_before_immediate_handler,
-	.after_immediate_handler	= smbd_impersonate_conn_vuid_after_immediate_handler,
-	.before_signal_handler		= smbd_impersonate_conn_vuid_before_signal_handler,
-	.after_signal_handler		= smbd_impersonate_conn_vuid_after_signal_handler,
-};
-
 struct tevent_context *smbd_impersonate_conn_vuid_create(
 				struct tevent_context *main_ev,
 				struct connection_struct *conn,
 				uint64_t vuid)
 {
-	struct tevent_context *ev = NULL;
-	struct smbd_impersonate_conn_vuid_state *state = NULL;
-
-	ev = tevent_context_wrapper_create(main_ev,
-					   conn,
-					   &smbd_impersonate_conn_vuid_ops,
-					   &state,
-					   struct smbd_impersonate_conn_vuid_state);
-	if (ev == NULL) {
-		return NULL;
-	}
-	state->conn = conn;
-	state->vuid = vuid;
-
-	return ev;
-}
-
-struct smbd_impersonate_conn_sess_state {
-	struct connection_struct *conn;
-	struct auth_session_info *session_info;
-};
-
-static bool smbd_impersonate_conn_sess_before_use(struct tevent_context *wrap_ev,
-						  void *private_data,
-						  struct tevent_context *main_ev,
-						  const char *location)
-{
-	struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
-		private_data, struct smbd_impersonate_conn_sess_state);
-	bool ok;
-
-	DEBUG(11,("%s: impersonating user[%s] wrap_ev[%p] main_ev[%p] "
-		  "location[%s] old uid[%ju] old gid[%ju] cwd[%s]\n",
-		  __func__, state->session_info->unix_info->unix_name,
-		  wrap_ev, main_ev, location,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name));
-
-	ok = become_user_by_session(state->conn, state->session_info);
-	if (!ok) {
-		return false;
-	}
-
-	DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
-		  __func__, state->conn->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name));
-
-	return true;
-}
-
-static void smbd_impersonate_conn_sess_after_use(struct tevent_context *wrap_ev,
-						 void *private_data,
-						 struct tevent_context *main_ev,
-						 const char *location)
-{
-	struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
-		private_data, struct smbd_impersonate_conn_sess_state);
-	bool ok;
-
-	DEBUG(11,("%s: deimpersonating[%s] uid[%ju] gid[%ju] cwd[%s] "
-		  "location[%s]\n",
-		  __func__, state->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name, location));
-
-	ok = unbecome_user();
-	if (!ok) {
-		smb_panic("smbd_impersonate_conn_sess_after_use() - failed");
-		return;
-	}
-
-	DEBUG(11,("%s: deimpersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
-		  __func__, state->conn->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name));
-}
-
-static void smbd_impersonate_conn_sess_before_fd_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_fd *fde,
-		uint16_t flags,
-		const char *handler_name,
-		const char *location)
-{
-	struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
-		private_data, struct smbd_impersonate_conn_sess_state);
-	bool ok;
-
-	DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
-		  __func__, fde, (uintmax_t)flags, handler_name, location));
-
-	ok = change_to_user_by_session(state->conn, state->session_info);
-	if (!ok) {
-		smb_panic("smbd_impersonate_conn_sess_before_fd_handler failed");
-		return;
-	}
-
-	DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
-		  __func__, state->conn->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name));
-}
-
-static void smbd_impersonate_conn_sess_after_fd_handler(struct tevent_context *wrap_ev,
-							void *private_data,
-							struct tevent_context *main_ev,
-							struct tevent_fd *fde,
-							uint16_t flags,
-							const char *handler_name,
-							const char *location)
-{
-	DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
-		  __func__, fde, handler_name, location));
-
-	/* be lazy and defer change_to_root_user() */
-}
-
-static void smbd_impersonate_conn_sess_before_timer_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_timer *te,
-		struct timeval requested_time,
-		struct timeval trigger_time,
-		const char *handler_name,
-		const char *location)
-{
-	struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
-		private_data, struct smbd_impersonate_conn_sess_state);
-	struct timeval_buf requested_buf;
-	struct timeval_buf trigger_buf;
-	bool ok;
-
-	DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
-		  "handler_name[%s] location[%s]\n",
-		  __func__, te,
-		  timeval_str_buf(&requested_time, true, true, &requested_buf),
-		  timeval_str_buf(&trigger_time, true, true, &trigger_buf),
-		  handler_name, location));
-
-	ok = change_to_user_by_session(state->conn, state->session_info);
-	if (!ok) {
-		smb_panic("smbd_impersonate_conn_sess_before_tm_handler failed");
-		return;
-	}
-
-	DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
-		  __func__, state->conn->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name));
-}
-
-static void smbd_impersonate_conn_sess_after_timer_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_timer *te,
-		struct timeval requested_time,
-		struct timeval trigger_time,
-		const char *handler_name,
-		const char *location)
-{
-	DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
-		  __func__, te, handler_name, location));
-
-	/* be lazy and defer change_to_root_user() */
-}
-
-static void smbd_impersonate_conn_sess_before_immediate_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_immediate *im,
-		const char *handler_name,
-		const char *location)
-{
-	struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
-		private_data, struct smbd_impersonate_conn_sess_state);
-	bool ok;
-
-	DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
-		  __func__, im, handler_name, location));
-
-	ok = change_to_user_by_session(state->conn, state->session_info);
-	if (!ok) {
-		smb_panic("smbd_impersonate_conn_sess_before_im_handler failed");
-		return;
-	}
-
-	DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
-		  __func__, state->conn->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name));
-}
-
-static void smbd_impersonate_conn_sess_after_immediate_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_immediate *im,
-		const char *handler_name,
-		const char *location)
-{
-	DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
-		  __func__, im, handler_name, location));
-
-	/* be lazy and defer unbecome_user() */
-}
-
-static void smbd_impersonate_conn_sess_before_signal_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_signal *se,
-		int signum,
-		int count,
-		void *siginfo,
-		const char *handler_name,
-		const char *location)
-{
-	struct smbd_impersonate_conn_sess_state *state = talloc_get_type_abort(
-		private_data, struct smbd_impersonate_conn_sess_state);
-	bool ok;
-
-	DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
-		  "handler_name[%s] location[%s]\n",
-		  __func__, se, signum, count, siginfo, handler_name, location));
-
-	ok = change_to_user_by_session(state->conn, state->session_info);
-	if (!ok) {
-		smb_panic("smbd_impersonate_conn_sess_before_si_handler failed");
-		return;
-	}
-
-	DEBUG(11,("%s: impersonated user[%s] uid[%ju] gid[%ju] cwd[%s]\n",
-		  __func__, state->conn->session_info->unix_info->unix_name,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  state->conn->cwd_fname->base_name));
-}
+	struct tevent_context *wrap_ev = NULL;
 
-static void smbd_impersonate_conn_sess_after_signal_handler(
-		struct tevent_context *wrap_ev,
-		void *private_data,
-		struct tevent_context *main_ev,
-		struct tevent_signal *se,
-		int signum,
-		int count,
-		void *siginfo,
-		const char *handler_name,
-		const char *location)
-{
-	DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
-		  __func__, se, handler_name, location));
+	wrap_ev = smbd_impersonate_debug_create(main_ev,
+						"conn_vuid",
+						DBGLVL_DEBUG);
 
-	/* be lazy and defer change_to_root_user() */
+	return wrap_ev;
 }
 
-static const struct tevent_wrapper_ops smbd_impersonate_conn_sess_ops = {
-	.name				= "smbd_impersonate_conn_sess",
-	.before_use			= smbd_impersonate_conn_sess_before_use,
-	.after_use			= smbd_impersonate_conn_sess_after_use,
-	.before_fd_handler		= smbd_impersonate_conn_sess_before_fd_handler,
-	.after_fd_handler		= smbd_impersonate_conn_sess_after_fd_handler,
-	.before_timer_handler		= smbd_impersonate_conn_sess_before_timer_handler,
-	.after_timer_handler		= smbd_impersonate_conn_sess_after_timer_handler,
-	.before_immediate_handler	= smbd_impersonate_conn_sess_before_immediate_handler,
-	.after_immediate_handler	= smbd_impersonate_conn_sess_after_immediate_handler,
-	.before_signal_handler		= smbd_impersonate_conn_sess_before_signal_handler,
-	.after_signal_handler		= smbd_impersonate_conn_sess_after_signal_handler,
-};
-
 struct tevent_context *smbd_impersonate_conn_sess_create(
 				struct tevent_context *main_ev,
 				struct connection_struct *conn,
 				struct auth_session_info *session_info)
 {
-	struct tevent_context *ev = NULL;
-	struct smbd_impersonate_conn_sess_state *state = NULL;
-
-	ev = tevent_context_wrapper_create(main_ev,
-					   conn,
-					   &smbd_impersonate_conn_sess_ops,
-					   &state,
-					   struct smbd_impersonate_conn_sess_state);
-	if (ev == NULL) {
-		return NULL;
-	}
-	state->conn = conn;
-	state->session_info = session_info;
-
-	return ev;
-}
-
-struct smbd_impersonate_root_state {
-	uint8_t _dummy;
-};
-
-static bool smbd_impersonate_root_before_use(struct tevent_context *wrap_ev,
-					     void *private_data,
-					     struct tevent_context *main_ev,
-					     const char *location)
-{
-	DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
-		  "uid[%ju] gid[%ju]\n",
-		  __func__, wrap_ev, main_ev, location,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid()));
-
-	become_root();
-	return true;
-}
-
-static void smbd_impersonate_root_after_use(struct tevent_context *wrap_ev,
-					    void *private_data,
-					    struct tevent_context *main_ev,
-					    const char *location)
-{
-	unbecome_root();
-
-	DEBUG(11,("%s: uid[%ju] gid[%ju] location[%s]\n",
-		  __func__, (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  location));
-}
-
-static void smbd_impersonate_root_before_fd_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_fd *fde,
-						uint16_t flags,
-						const char *handler_name,
-						const char *location)
-{
-	DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
-		  __func__, fde, (uintmax_t)flags, handler_name, location));
-
-	smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
-}
-
-static void smbd_impersonate_root_after_fd_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_fd *fde,
-						uint16_t flags,
-						const char *handler_name,
-						const char *location)
-{
-	DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
-		  __func__, fde, handler_name, location));
-
-	smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
-}
-
-static void smbd_impersonate_root_before_timer_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_timer *te,
-						struct timeval requested_time,
-						struct timeval trigger_time,
-						const char *handler_name,
-						const char *location)
-{
-	struct timeval_buf requested_buf;
-	struct timeval_buf trigger_buf;
-
-	DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
-		  "handler_name[%s] location[%s]\n",
-		  __func__, te,
-		  timeval_str_buf(&requested_time, true, true, &requested_buf),
-		  timeval_str_buf(&trigger_time, true, true, &trigger_buf),
-		  handler_name, location));
-
-	smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
-}
-
-static void smbd_impersonate_root_after_timer_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_timer *te,
-						struct timeval requested_time,
-						struct timeval trigger_time,
-						const char *handler_name,
-						const char *location)
-{
-	DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
-		  __func__, te, handler_name, location));
-
-	smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
-}
-
-static void smbd_impersonate_root_before_immediate_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_immediate *im,
-						const char *handler_name,
-						const char *location)
-{
-	DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
-		  __func__, im, handler_name, location));
-
-	smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
-}
-
-static void smbd_impersonate_root_after_immediate_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_immediate *im,
-						const char *handler_name,
-						const char *location)
-{
-	DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
-		  __func__, im, handler_name, location));
-
-	smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
-}
-
-static void smbd_impersonate_root_before_signal_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_signal *se,
-						int signum,
-						int count,
-						void *siginfo,
-						const char *handler_name,
-						const char *location)
-{
-	DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
-		  "handler_name[%s] location[%s]\n",
-		  __func__, se, signum, count, siginfo, handler_name, location));
+	struct tevent_context *wrap_ev = NULL;
 
-	smbd_impersonate_root_before_use(wrap_ev, private_data, main_ev, location);
-}
+	wrap_ev = smbd_impersonate_debug_create(main_ev,
+						"conn_sess",
+						DBGLVL_DEBUG);
 
-static void smbd_impersonate_root_after_signal_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_signal *se,
-						int signum,
-						int count,
-						void *siginfo,
-						const char *handler_name,
-						const char *location)
-{
-	DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
-		  __func__, se, handler_name, location));
-
-	smbd_impersonate_root_after_use(wrap_ev, private_data, main_ev, location);
+	return wrap_ev;
 }
 
-static const struct tevent_wrapper_ops smbd_impersonate_root_ops = {
-	.name				= "smbd_impersonate_root",
-	.before_use			= smbd_impersonate_root_before_use,
-	.after_use			= smbd_impersonate_root_after_use,
-	.before_fd_handler		= smbd_impersonate_root_before_fd_handler,
-	.after_fd_handler		= smbd_impersonate_root_after_fd_handler,
-	.before_timer_handler		= smbd_impersonate_root_before_timer_handler,
-	.after_timer_handler		= smbd_impersonate_root_after_timer_handler,
-	.before_immediate_handler	= smbd_impersonate_root_before_immediate_handler,
-	.after_immediate_handler	= smbd_impersonate_root_after_immediate_handler,
-	.before_signal_handler		= smbd_impersonate_root_before_signal_handler,
-	.after_signal_handler		= smbd_impersonate_root_after_signal_handler,
-};
-
 struct tevent_context *smbd_impersonate_root_create(struct tevent_context *main_ev)
 {
-	struct tevent_context *ev = NULL;
-	struct smbd_impersonate_root_state *state = NULL;
-
-	ev = tevent_context_wrapper_create(main_ev,
-					   main_ev,
-					   &smbd_impersonate_root_ops,
-					   &state,
-					   struct smbd_impersonate_root_state);
-	if (ev == NULL) {
-		return NULL;
-	}
-
-	return ev;
-}
-
-struct smbd_impersonate_guest_state {
-	uint8_t _dummy;
-};
-
-static bool smbd_impersonate_guest_before_use(struct tevent_context *wrap_ev,
-					      void *private_data,
-					      struct tevent_context *main_ev,
-					      const char *location)
-{
-	DEBUG(11,("%s: wrap_ev[%p] main_ev[%p] location[%s]"
-		  "uid[%ju] gid[%ju]\n",
-		  __func__, wrap_ev, main_ev, location,
-		  (uintmax_t)geteuid(), (uintmax_t)getegid()));
-
-	return become_guest();
-}
-
-static void smbd_impersonate_guest_after_use(struct tevent_context *wrap_ev,
-					     void *private_data,
-					     struct tevent_context *main_ev,
-					     const char *location)
-{
-	unbecome_guest();
-
-	DEBUG(11,("%s: uid[%ju] gid[%ju] location[%s]\n",
-		  __func__, (uintmax_t)geteuid(), (uintmax_t)getegid(),
-		  location));
-}
-
-static void smbd_impersonate_guest_before_fd_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_fd *fde,
-						uint16_t flags,
-						const char *handler_name,
-						const char *location)
-{
-	bool ok;
-
-	DEBUG(11,("%s: fde[%p] flags[%ju] handler_name[%s] location[%s]\n",
-		  __func__, fde, (uintmax_t)flags, handler_name, location));
-
-	ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
-					        main_ev, location);
-	if (!ok) {
-		smb_panic("smbd_impersonate_guest_before_use() - failed");
-		return;
-	}
-}
-
-static void smbd_impersonate_guest_after_fd_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_fd *fde,
-						uint16_t flags,
-						const char *handler_name,
-						const char *location)
-{
-	DEBUG(11,("%s: fde[%p] handler_name[%s] location[%s]\n",
-		  __func__, fde, handler_name, location));
-
-	smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
-}
-
-static void smbd_impersonate_guest_before_timer_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_timer *te,
-						struct timeval requested_time,
-						struct timeval trigger_time,
-						const char *handler_name,
-						const char *location)
-{
-	bool ok;
-	struct timeval_buf requested_buf;
-	struct timeval_buf trigger_buf;
-
-	DEBUG(11,("%s: te[%p] requested_time[%s] trigger_time[%s] "
-		  "handler_name[%s] location[%s]\n",
-		  __func__, te,
-		  timeval_str_buf(&requested_time, true, true, &requested_buf),
-		  timeval_str_buf(&trigger_time, true, true, &trigger_buf),
-		  handler_name, location));
-
-	ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
-					       main_ev, location);
-	if (!ok) {
-		smb_panic("smbd_impersonate_guest_before_use() - failed");
-		return;
-	}
-}
-
-static void smbd_impersonate_guest_after_timer_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_timer *te,
-						struct timeval requested_time,
-						struct timeval trigger_time,
-						const char *handler_name,
-						const char *location)
-{
-	DEBUG(11,("%s: te[%p] handler_name[%s] location[%s]\n",
-		  __func__, te, handler_name, location));
-
-	smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
-}
-
-static void smbd_impersonate_guest_before_immediate_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_immediate *im,
-						const char *handler_name,
-						const char *location)
-{
-	bool ok;
-
-	DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
-		  __func__, im, handler_name, location));
-
-	ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
-					       main_ev, location);
-	if (!ok) {
-		smb_panic("smbd_impersonate_guest_before_use() - failed");
-		return;
-	}
-}
-
-static void smbd_impersonate_guest_after_immediate_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_immediate *im,
-						const char *handler_name,
-						const char *location)
-{
-	DEBUG(11,("%s: im[%p] handler_name[%s] location[%s]\n",
-		  __func__, im, handler_name, location));
-
-	smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
-}
-
-static void smbd_impersonate_guest_before_signal_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_signal *se,
-						int signum,
-						int count,
-						void *siginfo,
-						const char *handler_name,
-						const char *location)
-{
-	bool ok;
-
-	DEBUG(11,("%s: se[%p] signum[%d] count[%d] siginfo[%p] "
-		  "handler_name[%s] location[%s]\n",
-		  __func__, se, signum, count, siginfo, handler_name, location));
-
-	ok = smbd_impersonate_guest_before_use(wrap_ev, private_data,
-					       main_ev, location);
-	if (!ok) {
-		smb_panic("smbd_impersonate_guest_before_use() - failed");
-		return;
-	}
-}
+	struct tevent_context *wrap_ev = NULL;
 
-static void smbd_impersonate_guest_after_signal_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_signal *se,
-						int signum,
-						int count,
-						void *siginfo,
-						const char *handler_name,
-						const char *location)
-{
-	DEBUG(11,("%s: se[%p] handler_name[%s] location[%s]\n",
-		  __func__, se, handler_name, location));
+	wrap_ev = smbd_impersonate_debug_create(main_ev,
+						"root",
+						DBGLVL_DEBUG);
 
-	smbd_impersonate_guest_after_use(wrap_ev, private_data, main_ev, location);
+	return wrap_ev;
 }
 
-static const struct tevent_wrapper_ops smbd_impersonate_guest_ops = {
-	.name				= "smbd_impersonate_guest",
-	.before_use			= smbd_impersonate_guest_before_use,
-	.after_use			= smbd_impersonate_guest_after_use,
-	.before_fd_handler		= smbd_impersonate_guest_before_fd_handler,
-	.after_fd_handler		= smbd_impersonate_guest_after_fd_handler,
-	.before_timer_handler		= smbd_impersonate_guest_before_timer_handler,
-	.after_timer_handler		= smbd_impersonate_guest_after_timer_handler,
-	.before_immediate_handler	= smbd_impersonate_guest_before_immediate_handler,
-	.after_immediate_handler	= smbd_impersonate_guest_after_immediate_handler,
-	.before_signal_handler		= smbd_impersonate_guest_before_signal_handler,
-	.after_signal_handler		= smbd_impersonate_guest_after_signal_handler,
-};
-
 struct tevent_context *smbd_impersonate_guest_create(struct tevent_context *main_ev)
 {
-	struct tevent_context *ev = NULL;
-	struct smbd_impersonate_guest_state *state = NULL;
-
-	ev = tevent_context_wrapper_create(main_ev,
-					   main_ev,
-					   &smbd_impersonate_guest_ops,
-					   &state,
-					   struct smbd_impersonate_guest_state);
-	if (ev == NULL) {
-		return NULL;
-	}
+	struct tevent_context *wrap_ev = NULL;
+
+	wrap_ev = smbd_impersonate_debug_create(main_ev,
+						"guest",
+						DBGLVL_DEBUG);
 
-	return ev;
+	return wrap_ev;
 }
-- 
2.17.1


From 7360cbc2546ebfafd39a37f045b7908a1804b5a0 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 11:38:34 +0100
Subject: [PATCH 35/66] Revert "smbd: make use of
 smbd_impersonate_{conn_vuid,conn_sess,root,guest}_create() wrappers"

This reverts commit 0dcaa0707bad67f7bfaa10ccaf167bfefbe87a0c.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/modules/vfs_readonly.c |  2 +-
 source3/smbd/conn.c            |  2 +-
 source3/smbd/msdfs.c           | 34 +++-------------------------------
 source3/smbd/process.c         | 18 ++----------------
 source3/smbd/uid.c             | 20 ++------------------
 5 files changed, 9 insertions(+), 67 deletions(-)

diff --git a/source3/modules/vfs_readonly.c b/source3/modules/vfs_readonly.c
index e7e12747a222..570eb7c4d15a 100644
--- a/source3/modules/vfs_readonly.c
+++ b/source3/modules/vfs_readonly.c
@@ -84,7 +84,7 @@ static int readonly_connect(vfs_handle_struct *handle,
       for (i=0; i< VUID_CACHE_SIZE; i++) {
         struct vuid_cache_entry *ent = &conn->vuid_cache->array[i];
         ent->vuid = UID_FIELD_INVALID;
-        TALLOC_FREE(ent->user_ev_ctx);
+        ent->user_ev_ctx = NULL;
         TALLOC_FREE(ent->session_info);
         ent->read_only = false;
         ent->share_access = 0;
diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c
index cfff6404608f..3b9aaac7834b 100644
--- a/source3/smbd/conn.c
+++ b/source3/smbd/conn.c
@@ -98,7 +98,7 @@ static void conn_clear_vuid_cache(connection_struct *conn, uint64_t vuid)
 			if (conn->user_ev_ctx == ent->user_ev_ctx) {
 				conn->user_ev_ctx = NULL;
 			}
-			TALLOC_FREE(ent->user_ev_ctx);
+			ent->user_ev_ctx = NULL;
 
 			/*
 			 * We need to keep conn->session_info around
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index 5283edbecfcd..a57716469716 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -264,17 +264,8 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx,
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	sconn->root_ev_ctx = smbd_impersonate_root_create(sconn->raw_ev_ctx);
-	if (sconn->root_ev_ctx == NULL) {
-		TALLOC_FREE(sconn);
-		return NT_STATUS_NO_MEMORY;
-	}
-	sconn->guest_ev_ctx = smbd_impersonate_guest_create(sconn->raw_ev_ctx);
-	if (sconn->guest_ev_ctx == NULL) {
-		TALLOC_FREE(sconn);
-		return NT_STATUS_NO_MEMORY;
-	}
-
+	sconn->root_ev_ctx = sconn->raw_ev_ctx;
+	sconn->guest_ev_ctx = sconn->raw_ev_ctx;
 	sconn->msg_ctx = msg;
 
 	conn = conn_new(sconn);
@@ -328,26 +319,7 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx,
 		vfs_user = get_current_username();
 	}
 
-	/*
-	 * The impersonation has to be done by the caller
-	 * of create_conn_struct_tos[_cwd]().
-	 *
-	 * Note: the context can't be changed anyway
-	 * as we're using our own tevent_context
-	 * and not a global one were other requests
-	 * could change the current unix token.
-	 *
-	 * We just use a wrapper tevent_context in order
-	 * to avoid crashes because TALLOC_FREE(conn->user_ev_ctx)
-	 * would also remove sconn->raw_ev_ctx.
-	 */
-	conn->user_ev_ctx = smbd_impersonate_debug_create(sconn->raw_ev_ctx,
-							  "FAKE impersonation",
-							  DBGLVL_DEBUG);
-	if (conn->user_ev_ctx == NULL) {
-		TALLOC_FREE(conn);
-		return NT_STATUS_NO_MEMORY;
-	}
+	conn->user_ev_ctx = sconn->raw_ev_ctx;
 
 	set_conn_connectpath(conn, connpath);
 
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index dc95af17393b..a3571ee811ab 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -3900,8 +3900,6 @@ void smbd_process(struct tevent_context *ev_ctx,
 		.ev = ev_ctx,
 		.frame = talloc_stackframe(),
 	};
-	struct tevent_context *root_ev_ctx = NULL;
-	struct tevent_context *guest_ev_ctx = NULL;
 	struct smbXsrv_client *client = NULL;
 	struct smbd_server_connection *sconn = NULL;
 	struct smbXsrv_connection *xconn = NULL;
@@ -3914,18 +3912,6 @@ void smbd_process(struct tevent_context *ev_ctx,
 	char *chroot_dir = NULL;
 	int rc;
 
-	root_ev_ctx = smbd_impersonate_root_create(ev_ctx);
-	if (root_ev_ctx == NULL) {
-		DEBUG(0,("smbd_impersonate_root_create() failed\n"));
-		exit_server_cleanly("smbd_impersonate_root_create().\n");
-	}
-
-	guest_ev_ctx = smbd_impersonate_guest_create(ev_ctx);
-	if (guest_ev_ctx == NULL) {
-		DEBUG(0,("smbd_impersonate_guest_create() failed\n"));
-		exit_server_cleanly("smbd_impersonate_guest_create().\n");
-	}
-
 	status = smbXsrv_client_create(ev_ctx, ev_ctx, msg_ctx, now, &client);
 	if (!NT_STATUS_IS_OK(status)) {
 		DBG_ERR("smbXsrv_client_create(): %s\n", nt_errstr(status));
@@ -3946,8 +3932,8 @@ void smbd_process(struct tevent_context *ev_ctx,
 	sconn->client = client;
 
 	sconn->raw_ev_ctx = ev_ctx;
-	sconn->root_ev_ctx = root_ev_ctx;
-	sconn->guest_ev_ctx = guest_ev_ctx;
+	sconn->root_ev_ctx = ev_ctx;
+	sconn->guest_ev_ctx = ev_ctx;
 	sconn->msg_ctx = msg_ctx;
 
 	ret = pthreadpool_tevent_init(sconn, lp_aio_max_threads(),
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index e7f0a8f620b8..2ce5366b7758 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -307,7 +307,7 @@ static void free_conn_session_info_if_unused(connection_struct *conn)
 		}
 	}
 	/* Not used, safe to free. */
-	TALLOC_FREE(conn->user_ev_ctx);
+	conn->user_ev_ctx = NULL;
 	TALLOC_FREE(conn->session_info);
 }
 
@@ -482,23 +482,7 @@ static bool check_user_ok(connection_struct *conn,
 		ent->session_info->unix_token->uid = sec_initial_uid();
 	}
 
-	if (vuid == UID_FIELD_INVALID) {
-		ent->user_ev_ctx = smbd_impersonate_conn_sess_create(
-			conn->sconn->raw_ev_ctx, conn, ent->session_info);
-		if (ent->user_ev_ctx == NULL) {
-			TALLOC_FREE(ent->session_info);
-			ent->vuid = UID_FIELD_INVALID;
-			return false;
-		}
-	} else {
-		ent->user_ev_ctx = smbd_impersonate_conn_vuid_create(
-			conn->sconn->raw_ev_ctx, conn, vuid);
-		if (ent->user_ev_ctx == NULL) {
-			TALLOC_FREE(ent->session_info);
-			ent->vuid = UID_FIELD_INVALID;
-			return false;
-		}
-	}
+	ent->user_ev_ctx = conn->sconn->raw_ev_ctx;
 
 	/*
 	 * It's actually OK to call check_user_ok() with
-- 
2.17.1


From cd76617e2ba3e710be67f316366434f986e1b38b Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 11:38:36 +0100
Subject: [PATCH 36/66] Revert "smbd: add simple noop
 smbd_impersonate_{conn_vuid,conn_sess,root,guest}_create() wrappers"

This reverts commit 5285966e67cbee8519015df12a15e938e85e6ee7.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/proto.h | 11 ----------
 source3/smbd/uid.c   | 50 --------------------------------------------
 2 files changed, 61 deletions(-)

diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index eb35a94862ac..8d0887851643 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -1244,17 +1244,6 @@ const struct security_unix_token *get_current_utok(connection_struct *conn);
 const struct security_token *get_current_nttok(connection_struct *conn);
 uint64_t get_current_vuid(connection_struct *conn);
 
-struct tevent_context *smbd_impersonate_conn_vuid_create(
-				struct tevent_context *main_ev,
-				struct connection_struct *conn,
-				uint64_t vuid);
-struct tevent_context *smbd_impersonate_conn_sess_create(
-				struct tevent_context *main_ev,
-				struct connection_struct *conn,
-				struct auth_session_info *session_info);
-struct tevent_context *smbd_impersonate_root_create(struct tevent_context *main_ev);
-struct tevent_context *smbd_impersonate_guest_create(struct tevent_context *main_ev);
-
 /* The following definitions come from smbd/utmp.c  */
 
 void sys_utmp_claim(const char *username, const char *hostname,
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index 2ce5366b7758..c850708bbe8e 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -958,53 +958,3 @@ uint64_t get_current_vuid(connection_struct *conn)
 {
 	return current_user.vuid;
 }
-
-struct tevent_context *smbd_impersonate_conn_vuid_create(
-				struct tevent_context *main_ev,
-				struct connection_struct *conn,
-				uint64_t vuid)
-{
-	struct tevent_context *wrap_ev = NULL;
-
-	wrap_ev = smbd_impersonate_debug_create(main_ev,
-						"conn_vuid",
-						DBGLVL_DEBUG);
-
-	return wrap_ev;
-}
-
-struct tevent_context *smbd_impersonate_conn_sess_create(
-				struct tevent_context *main_ev,
-				struct connection_struct *conn,
-				struct auth_session_info *session_info)
-{
-	struct tevent_context *wrap_ev = NULL;
-
-	wrap_ev = smbd_impersonate_debug_create(main_ev,
-						"conn_sess",
-						DBGLVL_DEBUG);
-
-	return wrap_ev;
-}
-
-struct tevent_context *smbd_impersonate_root_create(struct tevent_context *main_ev)
-{
-	struct tevent_context *wrap_ev = NULL;
-
-	wrap_ev = smbd_impersonate_debug_create(main_ev,
-						"root",
-						DBGLVL_DEBUG);
-
-	return wrap_ev;
-}
-
-struct tevent_context *smbd_impersonate_guest_create(struct tevent_context *main_ev)
-{
-	struct tevent_context *wrap_ev = NULL;
-
-	wrap_ev = smbd_impersonate_debug_create(main_ev,
-						"guest",
-						DBGLVL_DEBUG);
-
-	return wrap_ev;
-}
-- 
2.17.1


From 27561b78c4d0f2a6392cad60ffb2eab8adaff990 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 11:41:57 +0100
Subject: [PATCH 37/66] Revert "smbd: add smbd_impersonate_debug_create()
 helper"

This reverts commit 23319ef5a2eff4811b685d4ab54179efc49bac99.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/proto.h |   6 --
 source3/smbd/uid.c   | 229 -------------------------------------------
 2 files changed, 235 deletions(-)

diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index 8d0887851643..ba9ab501adbf 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -1211,12 +1211,6 @@ void reply_transs2(struct smb_request *req);
 
 /* The following definitions come from smbd/uid.c  */
 
-#define smbd_impersonate_debug_create(main_ev, name, dbg_lvl) \
-	_smbd_impersonate_debug_create(main_ev, name, dbg_lvl, __location__)
-struct tevent_context *_smbd_impersonate_debug_create(struct tevent_context *main_ev,
-						      const char *name,
-						      int dbg_lvl,
-						      const char *location);
 bool change_to_guest(void);
 NTSTATUS check_user_share_access(connection_struct *conn,
 				const struct auth_session_info *session_info,
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index c850708bbe8e..adf9e8c1c51a 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -26,235 +26,6 @@
 #include "passdb/lookup_sid.h"
 #include "auth.h"
 #include "../auth/auth_util.h"
-#include "lib/util/time_basic.h"
-
-struct smbd_impersonate_debug_state {
-	int dbg_lvl;
-	const char *name;
-};
-
-static bool smbd_impersonate_debug_before_use(struct tevent_context *wrap_ev,
-					      void *private_data,
-					      struct tevent_context *main_ev,
-					      const char *location)
-{
-	struct smbd_impersonate_debug_state *state =
-		(struct smbd_impersonate_debug_state *)private_data;
-
-	DEBUG(state->dbg_lvl, (
-	      "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
-	      __func__, state->name, wrap_ev, state, main_ev, location));
-
-	return true;
-}
-
-static void smbd_impersonate_debug_after_use(struct tevent_context *wrap_ev,
-					     void *private_data,
-					     struct tevent_context *main_ev,
-					     const char *location)
-{
-	struct smbd_impersonate_debug_state *state =
-		(struct smbd_impersonate_debug_state *)private_data;
-
-	DEBUG(state->dbg_lvl, (
-	      "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
-	      __func__, state->name, wrap_ev, state, main_ev, location));
-}
-
-static void smbd_impersonate_debug_before_fd_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_fd *fde,
-						uint16_t flags,
-						const char *handler_name,
-						const char *location)
-{
-	struct smbd_impersonate_debug_state *state =
-		(struct smbd_impersonate_debug_state *)private_data;
-
-	DEBUG(state->dbg_lvl, (
-	      "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
-	      "fde[%p] flags[0x%X] handler_name[%s] location[%s]\n",
-	      __func__, state->name, wrap_ev, state, main_ev,
-	      fde, flags, handler_name, location));
-}
-
-static void smbd_impersonate_debug_after_fd_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_fd *fde,
-						uint16_t flags,
-						const char *handler_name,
-						const char *location)
-{
-	struct smbd_impersonate_debug_state *state =
-		(struct smbd_impersonate_debug_state *)private_data;
-
-	DEBUG(state->dbg_lvl, (
-	      "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
-	      "fde[%p] flags[0x%X] handler_name[%s] location[%s]\n",
-	      __func__, state->name, wrap_ev, state, main_ev,
-	      fde, flags, handler_name, location));
-}
-
-static void smbd_impersonate_debug_before_timer_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_timer *te,
-						struct timeval requested_time,
-						struct timeval trigger_time,
-						const char *handler_name,
-						const char *location)
-{
-	struct smbd_impersonate_debug_state *state =
-		(struct smbd_impersonate_debug_state *)private_data;
-	struct timeval_buf requested_buf;
-	struct timeval_buf trigger_buf;
-
-	DEBUG(state->dbg_lvl, (
-	      "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
-	      "te[%p] requested_time[%s] trigger_time[%s] handler_name[%s] location[%s]\n",
-	      __func__, state->name, wrap_ev, state, main_ev, te,
-	      timeval_str_buf(&requested_time, true, true, &requested_buf),
-	      timeval_str_buf(&trigger_time, true, true, &trigger_buf),
-	      handler_name, location));
-}
-
-static void smbd_impersonate_debug_after_timer_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_timer *te,
-						struct timeval requested_time,
-						struct timeval trigger_time,
-						const char *handler_name,
-						const char *location)
-{
-	struct smbd_impersonate_debug_state *state =
-		(struct smbd_impersonate_debug_state *)private_data;
-	struct timeval_buf requested_buf;
-	struct timeval_buf trigger_buf;
-
-	DEBUG(state->dbg_lvl, (
-	      "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
-	      "te[%p] requested_time[%s] trigger_time[%s] handler_name[%s] location[%s]\n",
-	      __func__, state->name, wrap_ev, state, main_ev, te,
-	      timeval_str_buf(&requested_time, true, true, &requested_buf),
-	      timeval_str_buf(&trigger_time, true, true, &trigger_buf),
-	      handler_name, location));
-}
-
-static void smbd_impersonate_debug_before_immediate_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_immediate *im,
-						const char *handler_name,
-						const char *location)
-{
-	struct smbd_impersonate_debug_state *state =
-		(struct smbd_impersonate_debug_state *)private_data;
-
-	DEBUG(state->dbg_lvl, (
-	      "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
-	      "im[%p] handler_name[%s] location[%s]\n",
-	      __func__, state->name, wrap_ev, state, main_ev,
-	      im, handler_name, location));
-}
-
-static void smbd_impersonate_debug_after_immediate_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_immediate *im,
-						const char *handler_name,
-						const char *location)
-{
-	struct smbd_impersonate_debug_state *state =
-		(struct smbd_impersonate_debug_state *)private_data;
-
-	DEBUG(state->dbg_lvl, (
-	      "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
-	      "im[%p] handler_name[%s] location[%s]\n",
-	      __func__, state->name, wrap_ev, state, main_ev,
-	      im, handler_name, location));
-}
-
-static void smbd_impersonate_debug_before_signal_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_signal *se,
-						int signum,
-						int count,
-						void *siginfo,
-						const char *handler_name,
-						const char *location)
-{
-	struct smbd_impersonate_debug_state *state =
-		(struct smbd_impersonate_debug_state *)private_data;
-
-	DEBUG(state->dbg_lvl, (
-	      "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
-	      "se[%p] signum[%d] count[%d] siginfo[%p] handler_name[%s] location[%s]\n",
-	      __func__, state->name, wrap_ev, state, main_ev,
-	      se, signum, count, siginfo, handler_name, location));
-}
-
-static void smbd_impersonate_debug_after_signal_handler(struct tevent_context *wrap_ev,
-						void *private_data,
-						struct tevent_context *main_ev,
-						struct tevent_signal *se,
-						int signum,
-						int count,
-						void *siginfo,
-						const char *handler_name,
-						const char *location)
-{
-	struct smbd_impersonate_debug_state *state =
-		(struct smbd_impersonate_debug_state *)private_data;
-
-	DEBUG(state->dbg_lvl, (
-	      "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] "
-	      "se[%p] signum[%d] count[%d] siginfo[%p] handler_name[%s] location[%s]\n",
-	      __func__, state->name, wrap_ev, state, main_ev,
-	      se, signum, count, siginfo, handler_name, location));
-}
-
-static const struct tevent_wrapper_ops smbd_impersonate_debug_ops = {
-	.name				= "smbd_impersonate_debug",
-	.before_use			= smbd_impersonate_debug_before_use,
-	.after_use			= smbd_impersonate_debug_after_use,
-	.before_fd_handler		= smbd_impersonate_debug_before_fd_handler,
-	.after_fd_handler		= smbd_impersonate_debug_after_fd_handler,
-	.before_timer_handler		= smbd_impersonate_debug_before_timer_handler,
-	.after_timer_handler		= smbd_impersonate_debug_after_timer_handler,
-	.before_immediate_handler	= smbd_impersonate_debug_before_immediate_handler,
-	.after_immediate_handler	= smbd_impersonate_debug_after_immediate_handler,
-	.before_signal_handler		= smbd_impersonate_debug_before_signal_handler,
-	.after_signal_handler		= smbd_impersonate_debug_after_signal_handler,
-};
-
-struct tevent_context *_smbd_impersonate_debug_create(struct tevent_context *main_ev,
-						      const char *name,
-						      int dbg_lvl,
-						      const char *location)
-{
-	struct tevent_context *wrap_ev = NULL;
-	struct smbd_impersonate_debug_state *state = NULL;
-
-	wrap_ev = tevent_context_wrapper_create(main_ev,
-					main_ev,
-					&smbd_impersonate_debug_ops,
-					&state,
-					struct smbd_impersonate_debug_state);
-	if (wrap_ev == NULL) {
-		return NULL;
-	}
-	state->name = name;
-	state->dbg_lvl = dbg_lvl;
-	DEBUG(state->dbg_lvl, (
-	      "%s: name[%s] wrap_ev[%p] state[%p] main_ev[%p] location[%s]\n",
-	      __func__, state->name, wrap_ev, state, main_ev, location));
-
-	return wrap_ev;
-}
 
 /* what user is current? */
 extern struct current_user current_user;
-- 
2.17.1


From 16cf79503b1435b99cb014c8ebe7f9f3293f8df7 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 11:42:45 +0100
Subject: [PATCH 38/66] Revert "smbd: add [un]become_guest() helper functions"

This reverts commit 7b5a47b84696e8e5c26207bd398742b883e598c2.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/proto.h |  2 --
 source3/smbd/uid.c   | 28 ----------------------------
 2 files changed, 30 deletions(-)

diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index ba9ab501adbf..3662a925dd6c 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -1225,8 +1225,6 @@ void become_root(void);
 void unbecome_root(void);
 void smbd_become_root(void);
 void smbd_unbecome_root(void);
-bool become_guest(void);
-void unbecome_guest(void);
 bool become_user(connection_struct *conn, uint64_t vuid);
 bool become_user_by_fsp(struct files_struct *fsp);
 bool become_user_by_session(connection_struct *conn,
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index adf9e8c1c51a..f902f2aeae38 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -599,34 +599,6 @@ void smbd_unbecome_root(void)
 	pop_conn_ctx();
 }
 
-bool become_guest(void)
-{
-	bool ok;
-
-	ok = push_sec_ctx();
-	if (!ok) {
-		return false;
-	}
-
-	push_conn_ctx();
-
-	ok = change_to_guest();
-	if (!ok) {
-		pop_sec_ctx();
-		pop_conn_ctx();
-		return false;
-	}
-
-	return true;
-}
-
-void unbecome_guest(void)
-{
-	pop_sec_ctx();
-	pop_conn_ctx();
-	return;
-}
-
 /****************************************************************************
  Push the current security context then force a change via change_to_user().
  Saves and restores the connection context.
-- 
2.17.1


From caf69a6d2c44bad70861c6ca40f667d403f21aa8 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 12:41:25 +0100
Subject: [PATCH 39/66] Revert "s4:messaging: make sure only
 imessaging_client_init() can be used with a wrapper tevent_context wrapper"

This reverts commit e186d6a06b1b300256a2cb4138f0532d518d0597.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source4/lib/messaging/messaging.c | 28 ++--------------------------
 1 file changed, 2 insertions(+), 26 deletions(-)

diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c
index 59c48cd44cb4..6c10289515f5 100644
--- a/source4/lib/messaging/messaging.c
+++ b/source4/lib/messaging/messaging.c
@@ -361,7 +361,7 @@ NTSTATUS imessaging_reinit_all(void)
 /*
   create the listening socket and setup the dispatcher
 */
-static struct imessaging_context *imessaging_init_internal(TALLOC_CTX *mem_ctx,
+struct imessaging_context *imessaging_init(TALLOC_CTX *mem_ctx,
 					   struct loadparm_context *lp_ctx,
 					   struct server_id server_id,
 					   struct tevent_context *ev)
@@ -625,30 +625,6 @@ static void imessaging_dgm_recv(struct tevent_context *ev,
 	}
 }
 
-struct imessaging_context *imessaging_init(TALLOC_CTX *mem_ctx,
-					   struct loadparm_context *lp_ctx,
-					   struct server_id server_id,
-					   struct tevent_context *ev)
-{
-	if (ev == NULL) {
-		return NULL;
-	}
-
-	if (tevent_context_is_wrapper(ev)) {
-		/*
-		 * This is really a programmer error!
-		 *
-		 * The main/raw tevent context should
-		 * have been registered first!
-		 */
-		DBG_ERR("Should not be used with a wrapper tevent context\n");
-		errno = EINVAL;
-		return NULL;
-	}
-
-	return imessaging_init_internal(mem_ctx, lp_ctx, server_id, ev);
-}
-
 /*
    A hack, for the short term until we get 'client only' messaging in place
 */
@@ -665,7 +641,7 @@ struct imessaging_context *imessaging_client_init(TALLOC_CTX *mem_ctx,
 	/* This is because we are not in the s3 serverid database */
 	id.unique_id = SERVERID_UNIQUE_ID_NOT_TO_VERIFY;
 
-	return imessaging_init_internal(mem_ctx, lp_ctx, id, ev);
+	return imessaging_init(mem_ctx, lp_ctx, id, ev);
 }
 /*
   a list of registered irpc server functions
-- 
2.17.1


From a0322344792ad9941d930f601553abdd63a2df43 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 12:45:15 +0100
Subject: [PATCH 40/66] Revert "s3:messages: allow
 messaging_filtered_read_send() to use wrapper tevent_context"

This reverts commit 2b05f1098187e00166649c8ea7c63e6901b9d242.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/lib/messages.c | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index aa899142333d..864d758fb13e 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -206,7 +206,7 @@ static bool messaging_register_event_context(struct messaging_context *ctx,
 			continue;
 		}
 
-		if (tevent_context_same_loop(reg->ev, ev)) {
+		if (reg->ev == ev) {
 			reg->refcount += 1;
 			return true;
 		}
@@ -255,7 +255,7 @@ static bool messaging_deregister_event_context(struct messaging_context *ctx,
 			continue;
 		}
 
-		if (tevent_context_same_loop(reg->ev, ev)) {
+		if (reg->ev == ev) {
 			reg->refcount -= 1;
 
 			if (reg->refcount == 0) {
@@ -1025,9 +1025,7 @@ struct tevent_req *messaging_filtered_read_send(
 	state->filter = filter;
 	state->private_data = private_data;
 
-	if (tevent_context_is_wrapper(ev) &&
-	    !tevent_context_same_loop(ev, msg_ctx->event_ctx))
-	{
+	if (tevent_context_is_wrapper(ev)) {
 		/* This is really a programmer error! */
 		DBG_ERR("Wrapper tevent context doesn't use main context.\n");
 		tevent_req_error(req, EINVAL);
@@ -1036,11 +1034,7 @@ struct tevent_req *messaging_filtered_read_send(
 
 	/*
 	 * We have to defer the callback here, as we might be called from
-	 * within a different tevent_context than state->ev.
-	 *
-	 * This is important for two cases:
-	 * 1. nested event contexts, used by blocking ctdb calls
-	 * 2. possible impersonation using wrapper tevent contexts.
+	 * within a different tevent_context than state->ev
 	 */
 	tevent_req_defer_callback(req, state->ev);
 
@@ -1336,7 +1330,7 @@ static bool messaging_dispatch_waiters(struct messaging_context *msg_ctx,
 
 		state = tevent_req_data(
 			req, struct messaging_filtered_read_state);
-		if (tevent_context_same_loop(ev, state->ev) &&
+		if ((ev == state->ev) &&
 		    state->filter(rec, state->private_data)) {
 			messaging_filtered_read_done(req, rec);
 			return true;
-- 
2.17.1


From cc606f6f7f5e3e2ce8dd18ad4e52426c11d47d19 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 12:45:28 +0100
Subject: [PATCH 41/66] Revert "s3:messages: allow messaging_dgm_ref() to use
 wrapper tevent_context"

This reverts commit 9dc332060cf5f249ea887dbc60ec7a39b6f91120.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/lib/messages_dgm_ref.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/source3/lib/messages_dgm_ref.c b/source3/lib/messages_dgm_ref.c
index 12ff21ca6283..fd1709617468 100644
--- a/source3/lib/messages_dgm_ref.c
+++ b/source3/lib/messages_dgm_ref.c
@@ -55,6 +55,18 @@ void *messaging_dgm_ref(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
 {
 	struct msg_dgm_ref *result, *tmp_refs;
 
+	if (tevent_context_is_wrapper(ev)) {
+		/*
+		 * This is really a programmer error!
+		 *
+		 * The main/raw tevent context should
+		 * have been registered first!
+		 */
+		DBG_ERR("Should not be used with a wrapper tevent context\n");
+		*err = EINVAL;
+		return NULL;
+	}
+
 	result = talloc(mem_ctx, struct msg_dgm_ref);
 	if (result == NULL) {
 		*err = ENOMEM;
@@ -75,18 +87,6 @@ void *messaging_dgm_ref(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
 	if (refs == NULL) {
 		int ret;
 
-		if (tevent_context_is_wrapper(ev)) {
-			/*
-			 * This is really a programmer error!
-			 *
-			 * The main/raw tevent context should
-			 * have been registered first!
-			 */
-			DBG_ERR("Should not be used with a wrapper tevent context\n");
-			*err = EINVAL;
-			return NULL;
-		}
-
 		ret = messaging_dgm_init(ev, unique, socket_dir, lockfile_dir,
 					 msg_dgm_ref_recv, NULL);
 		DBG_DEBUG("messaging_dgm_init returned %s\n", strerror(ret));
-- 
2.17.1


From 0651f884a500e9972d8a39932e82ec027c979882 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 12:45:42 +0100
Subject: [PATCH 42/66] Revert "s3:messages: allow
 messaging_{dgm,ctdb}_register_tevent_context() to use wrapper tevent_context"

This reverts commit 660cf86639753edaa7a7a21a5b5ae207ae7d4260.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/lib/messages_ctdb.c | 38 +++++++++----------------------------
 source3/lib/messages_dgm.c  | 38 +++++++++----------------------------
 2 files changed, 18 insertions(+), 58 deletions(-)

diff --git a/source3/lib/messages_ctdb.c b/source3/lib/messages_ctdb.c
index 11fe72661cc3..a1aeb37af198 100644
--- a/source3/lib/messages_ctdb.c
+++ b/source3/lib/messages_ctdb.c
@@ -209,6 +209,14 @@ struct messaging_ctdb_fde *messaging_ctdb_register_tevent_context(
 		return NULL;
 	}
 
+	if (tevent_context_is_wrapper(ev)) {
+		/*
+		 * This is really a programmer error!
+		 */
+		DBG_ERR("Should not be used with a wrapper tevent context\n");
+		return NULL;
+	}
+
 	fde = talloc(mem_ctx, struct messaging_ctdb_fde);
 	if (fde == NULL) {
 		return NULL;
@@ -226,24 +234,7 @@ struct messaging_ctdb_fde *messaging_ctdb_register_tevent_context(
 			 */
 			continue;
 		}
-
-		/*
-		 * We can only have one tevent_fd
-		 * per low level tevent_context.
-		 *
-		 * This means any wrapper tevent_context
-		 * needs to share the structure with
-		 * the main tevent_context and/or
-		 * any sibling wrapper tevent_context.
-		 *
-		 * This means we need to use tevent_context_same_loop()
-		 * instead of just (fde_ev->ev == ev).
-		 *
-		 * Note: the tevent_context_is_wrapper() check below
-		 * makes sure that fde_ev->ev is always a raw
-		 * tevent context.
-		 */
-		if (tevent_context_same_loop(fde_ev->ev, ev)) {
+		if (fde_ev->ev == ev) {
 			break;
 		}
 	}
@@ -251,17 +242,6 @@ struct messaging_ctdb_fde *messaging_ctdb_register_tevent_context(
 	if (fde_ev == NULL) {
 		int sock = ctdbd_conn_get_fd(ctx->conn);
 
-		if (tevent_context_is_wrapper(ev)) {
-			/*
-			 * This is really a programmer error!
-			 *
-			 * The main/raw tevent context should
-			 * have been registered first!
-			 */
-			DBG_ERR("Should not be used with a wrapper tevent context\n");
-			return NULL;
-		}
-
 		fde_ev = talloc(fde, struct messaging_ctdb_fde_ev);
 		if (fde_ev == NULL) {
 			return NULL;
diff --git a/source3/lib/messages_dgm.c b/source3/lib/messages_dgm.c
index af12be8d82eb..a661a16c99aa 100644
--- a/source3/lib/messages_dgm.c
+++ b/source3/lib/messages_dgm.c
@@ -1683,6 +1683,14 @@ struct messaging_dgm_fde *messaging_dgm_register_tevent_context(
 		return NULL;
 	}
 
+	if (tevent_context_is_wrapper(ev)) {
+		/*
+		 * This is really a programmer error!
+		 */
+		DBG_ERR("Should not be used with a wrapper tevent context\n");
+		return NULL;
+	}
+
 	fde = talloc(mem_ctx, struct messaging_dgm_fde);
 	if (fde == NULL) {
 		return NULL;
@@ -1700,40 +1708,12 @@ struct messaging_dgm_fde *messaging_dgm_register_tevent_context(
 			 */
 			continue;
 		}
-
-		/*
-		 * We can only have one tevent_fd
-		 * per low level tevent_context.
-		 *
-		 * This means any wrapper tevent_context
-		 * needs to share the structure with
-		 * the main tevent_context and/or
-		 * any sibling wrapper tevent_context.
-		 *
-		 * This means we need to use tevent_context_same_loop()
-		 * instead of just (fde_ev->ev == ev).
-		 *
-		 * Note: the tevent_context_is_wrapper() check below
-		 * makes sure that fde_ev->ev is always a raw
-		 * tevent context.
-		 */
-		if (tevent_context_same_loop(fde_ev->ev, ev)) {
+		if (fde_ev->ev == ev) {
 			break;
 		}
 	}
 
 	if (fde_ev == NULL) {
-		if (tevent_context_is_wrapper(ev)) {
-			/*
-			 * This is really a programmer error!
-			 *
-			 * The main/raw tevent context should
-			 * have been registered first!
-			 */
-			DBG_ERR("Should not be used with a wrapper tevent context\n");
-			return NULL;
-		}
-
 		fde_ev = talloc(fde, struct messaging_dgm_fde_ev);
 		if (fde_ev == NULL) {
 			return NULL;
-- 
2.17.1


From 5b74214c10c8d45b336af38395fafd9db091643f Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 12:48:30 +0100
Subject: [PATCH 43/66] Revert "s3:messages: protect against usage of wrapper
 tevent_context objects for messaging"

This reverts commit 7f2afc20e1b6397c364a98d1be006377c95e4665.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/lib/messages.c          | 23 -----------------------
 source3/lib/messages_ctdb.c     |  8 --------
 source3/lib/messages_ctdb_ref.c | 12 ------------
 source3/lib/messages_dgm.c      | 14 --------------
 source3/lib/messages_dgm_ref.c  | 12 ------------
 5 files changed, 69 deletions(-)

diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index 864d758fb13e..dd19173b9736 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -365,11 +365,6 @@ static bool messaging_alert_event_contexts(struct messaging_context *ctx)
 		 * alternatively would be to track whether the
 		 * immediate has already been scheduled. For
 		 * now, avoid that complexity here.
-		 *
-		 * reg->ev and ctx->event_ctx can't
-		 * be wrapper tevent_context pointers
-		 * so we don't need to use
-		 * tevent_context_same_loop().
 		 */
 
 		if (reg->ev == ctx->event_ctx) {
@@ -498,12 +493,6 @@ static NTSTATUS messaging_init_internal(TALLOC_CTX *mem_ctx,
 
 	sec_init();
 
-	if (tevent_context_is_wrapper(ev)) {
-		/* This is really a programmer error! */
-		DBG_ERR("Should not be used with a wrapper tevent context\n");
-		return NT_STATUS_INVALID_PARAMETER;
-	}
-
 	lck_path = lock_path(talloc_tos(), "msg.lock");
 	if (lck_path == NULL) {
 		return NT_STATUS_NO_MEMORY;
@@ -1025,13 +1014,6 @@ struct tevent_req *messaging_filtered_read_send(
 	state->filter = filter;
 	state->private_data = private_data;
 
-	if (tevent_context_is_wrapper(ev)) {
-		/* This is really a programmer error! */
-		DBG_ERR("Wrapper tevent context doesn't use main context.\n");
-		tevent_req_error(req, EINVAL);
-		return tevent_req_post(req, ev);
-	}
-
 	/*
 	 * We have to defer the callback here, as we might be called from
 	 * within a different tevent_context than state->ev
@@ -1352,11 +1334,6 @@ static void messaging_dispatch_rec(struct messaging_context *msg_ctx,
 	bool consumed;
 	size_t i;
 
-	/*
-	 * ev and msg_ctx->event_ctx can't be wrapper tevent_context pointers
-	 * so we don't need to use tevent_context_same_loop().
-	 */
-
 	if (ev == msg_ctx->event_ctx) {
 		consumed = messaging_dispatch_classic(msg_ctx, rec);
 		if (consumed) {
diff --git a/source3/lib/messages_ctdb.c b/source3/lib/messages_ctdb.c
index a1aeb37af198..d3e2e3f85893 100644
--- a/source3/lib/messages_ctdb.c
+++ b/source3/lib/messages_ctdb.c
@@ -209,14 +209,6 @@ struct messaging_ctdb_fde *messaging_ctdb_register_tevent_context(
 		return NULL;
 	}
 
-	if (tevent_context_is_wrapper(ev)) {
-		/*
-		 * This is really a programmer error!
-		 */
-		DBG_ERR("Should not be used with a wrapper tevent context\n");
-		return NULL;
-	}
-
 	fde = talloc(mem_ctx, struct messaging_ctdb_fde);
 	if (fde == NULL) {
 		return NULL;
diff --git a/source3/lib/messages_ctdb_ref.c b/source3/lib/messages_ctdb_ref.c
index 47b4b758dac5..3570ed8ae4c8 100644
--- a/source3/lib/messages_ctdb_ref.c
+++ b/source3/lib/messages_ctdb_ref.c
@@ -52,18 +52,6 @@ void *messaging_ctdb_ref(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
 {
 	struct msg_ctdb_ref *result, *tmp_refs;
 
-	if (tevent_context_is_wrapper(ev)) {
-		/*
-		 * This is really a programmer error!
-		 *
-		 * The main/raw tevent context should
-		 * have been registered first!
-		 */
-		DBG_ERR("Should not be used with a wrapper tevent context\n");
-		*err = EINVAL;
-		return NULL;
-	}
-
 	result = talloc(mem_ctx, struct msg_ctdb_ref);
 	if (result == NULL) {
 		*err = ENOMEM;
diff --git a/source3/lib/messages_dgm.c b/source3/lib/messages_dgm.c
index a661a16c99aa..37eefeb0a4a7 100644
--- a/source3/lib/messages_dgm.c
+++ b/source3/lib/messages_dgm.c
@@ -993,12 +993,6 @@ int messaging_dgm_init(struct tevent_context *ev,
 		return EEXIST;
 	}
 
-	if (tevent_context_is_wrapper(ev)) {
-		/* This is really a programmer error! */
-		DBG_ERR("Should not be used with a wrapper tevent context\n");
-		return EINVAL;
-	}
-
 	ctx = talloc_zero(NULL, struct messaging_dgm_context);
 	if (ctx == NULL) {
 		goto fail_nomem;
@@ -1683,14 +1677,6 @@ struct messaging_dgm_fde *messaging_dgm_register_tevent_context(
 		return NULL;
 	}
 
-	if (tevent_context_is_wrapper(ev)) {
-		/*
-		 * This is really a programmer error!
-		 */
-		DBG_ERR("Should not be used with a wrapper tevent context\n");
-		return NULL;
-	}
-
 	fde = talloc(mem_ctx, struct messaging_dgm_fde);
 	if (fde == NULL) {
 		return NULL;
diff --git a/source3/lib/messages_dgm_ref.c b/source3/lib/messages_dgm_ref.c
index fd1709617468..470dfbeabc74 100644
--- a/source3/lib/messages_dgm_ref.c
+++ b/source3/lib/messages_dgm_ref.c
@@ -55,18 +55,6 @@ void *messaging_dgm_ref(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
 {
 	struct msg_dgm_ref *result, *tmp_refs;
 
-	if (tevent_context_is_wrapper(ev)) {
-		/*
-		 * This is really a programmer error!
-		 *
-		 * The main/raw tevent context should
-		 * have been registered first!
-		 */
-		DBG_ERR("Should not be used with a wrapper tevent context\n");
-		*err = EINVAL;
-		return NULL;
-	}
-
 	result = talloc(mem_ctx, struct msg_dgm_ref);
 	if (result == NULL) {
 		*err = ENOMEM;
-- 
2.17.1


From d19e296835deb13d4b12b3d4bf20f7bc3f56f711 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:17:22 +0100
Subject: [PATCH 44/66] Revert "smbd: remove unused
 smbd_server_connection->ev_ctx"

This reverts commit 721fbbfa7001b2788602106101f0407483894322.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/globals.h | 1 +
 source3/smbd/msdfs.c   | 1 +
 source3/smbd/process.c | 1 +
 3 files changed, 3 insertions(+)

diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 5695663cc665..a13916e230ab 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -879,6 +879,7 @@ struct smbd_server_connection {
 	const struct tsocket_address *local_address;
 	const struct tsocket_address *remote_address;
 	const char *remote_hostname;
+	struct tevent_context *ev_ctx;
 	struct tevent_context *raw_ev_ctx;
 	struct tevent_context *root_ev_ctx;
 	struct tevent_context *guest_ev_ctx;
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index a57716469716..c523abb3158c 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -264,6 +264,7 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx,
 		return NT_STATUS_NO_MEMORY;
 	}
 
+	sconn->ev_ctx = sconn->raw_ev_ctx;
 	sconn->root_ev_ctx = sconn->raw_ev_ctx;
 	sconn->guest_ev_ctx = sconn->raw_ev_ctx;
 	sconn->msg_ctx = msg;
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index a3571ee811ab..e730676ef361 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -3931,6 +3931,7 @@ void smbd_process(struct tevent_context *ev_ctx,
 	client->sconn = sconn;
 	sconn->client = client;
 
+	sconn->ev_ctx = ev_ctx;
 	sconn->raw_ev_ctx = ev_ctx;
 	sconn->root_ev_ctx = ev_ctx;
 	sconn->guest_ev_ctx = ev_ctx;
-- 
2.17.1


From 315ec1da4d1944bacbb3977a211ffc86f78c9e67 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:18:55 +0100
Subject: [PATCH 45/66] Revert "smbd: add an effective
 {smb,smbd_smb2}_request->ev_ctx that holds the event context used for the
 request processing"

This reverts commit 894e5001c747ce765dad5517778dda55d7d1f4d9.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/include/vfs.h                | 2 --
 source3/smbd/aio.c                   | 8 ++++----
 source3/smbd/globals.h               | 3 ---
 source3/smbd/ipc.c                   | 4 ++--
 source3/smbd/open.c                  | 8 ++++----
 source3/smbd/pipes.c                 | 8 ++++----
 source3/smbd/process.c               | 8 --------
 source3/smbd/reply.c                 | 2 +-
 source3/smbd/smb2_break.c            | 4 ++--
 source3/smbd/smb2_close.c            | 2 +-
 source3/smbd/smb2_create.c           | 6 +++---
 source3/smbd/smb2_flush.c            | 2 +-
 source3/smbd/smb2_getinfo.c          | 2 +-
 source3/smbd/smb2_glue.c             | 1 -
 source3/smbd/smb2_ioctl.c            | 2 +-
 source3/smbd/smb2_ioctl_named_pipe.c | 2 +-
 source3/smbd/smb2_lock.c             | 4 ++--
 source3/smbd/smb2_notify.c           | 4 ++--
 source3/smbd/smb2_query_directory.c  | 2 +-
 source3/smbd/smb2_read.c             | 2 +-
 source3/smbd/smb2_server.c           | 2 --
 source3/smbd/smb2_sesssetup.c        | 4 ++--
 source3/smbd/smb2_setinfo.c          | 2 +-
 source3/smbd/smb2_tcon.c             | 4 ++--
 source3/smbd/smb2_write.c            | 2 +-
 25 files changed, 37 insertions(+), 53 deletions(-)

diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 959dd4059151..1a05283fe6cc 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -518,8 +518,6 @@ struct smb_request {
 
 	size_t unread_bytes;
 	bool encrypted;
-	/* the tevent_context (wrapper) the request operates on */
-	struct tevent_context *ev_ctx;
 	connection_struct *conn;
 	struct smbd_server_connection *sconn;
 	struct smbXsrv_connection *xconn;
diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c
index 29723d23fa52..8ac3ef7278ec 100644
--- a/source3/smbd/aio.c
+++ b/source3/smbd/aio.c
@@ -206,7 +206,7 @@ NTSTATUS schedule_aio_read_and_X(connection_struct *conn,
 	aio_ex->nbyte = smb_maxcnt;
 	aio_ex->offset = startpos;
 
-	req = SMB_VFS_PREAD_SEND(aio_ex, smbreq->ev_ctx,
+	req = SMB_VFS_PREAD_SEND(aio_ex, fsp->conn->sconn->ev_ctx,
 				 fsp,
 				 smb_buf(aio_ex->outbuf.data) + 1 /* pad */,
 				 smb_maxcnt, startpos);
@@ -459,7 +459,7 @@ NTSTATUS schedule_aio_write_and_X(connection_struct *conn,
 	aio_ex->nbyte = numtowrite;
 	aio_ex->offset = startpos;
 
-	req = pwrite_fsync_send(aio_ex, smbreq->ev_ctx, fsp,
+	req = pwrite_fsync_send(aio_ex, fsp->conn->sconn->ev_ctx, fsp,
 				data, numtowrite, startpos,
 				aio_ex->write_through);
 	if (req == NULL) {
@@ -705,7 +705,7 @@ NTSTATUS schedule_smb2_aio_read(connection_struct *conn,
 	aio_ex->nbyte = smb_maxcnt;
 	aio_ex->offset = startpos;
 
-	req = SMB_VFS_PREAD_SEND(aio_ex, smbreq->ev_ctx, fsp,
+	req = SMB_VFS_PREAD_SEND(aio_ex, fsp->conn->sconn->ev_ctx, fsp,
 				 preadbuf->data, smb_maxcnt, startpos);
 	if (req == NULL) {
 		DEBUG(0, ("smb2: SMB_VFS_PREAD_SEND failed. "
@@ -846,7 +846,7 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn,
 	aio_ex->nbyte = in_data.length;
 	aio_ex->offset = in_offset;
 
-	req = pwrite_fsync_send(aio_ex, smbreq->ev_ctx, fsp,
+	req = pwrite_fsync_send(aio_ex, fsp->conn->sconn->ev_ctx, fsp,
 				in_data.data, in_data.length, in_offset,
 				write_through);
 	if (req == NULL) {
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index a13916e230ab..a273cdb3651e 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -705,9 +705,6 @@ struct smbd_smb2_request {
 	struct smbXsrv_tcon *tcon;
 	uint32_t last_tid;
 
-	/* the tevent_context (wrapper) the request operates on */
-	struct tevent_context *ev_ctx;
-
 	int current_idx;
 	bool do_signing;
 	/* Was the request encrypted? */
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index 85236e0102f2..f1c8ea0c2ed4 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -281,7 +281,7 @@ static void api_dcerpc_cmd(connection_struct *conn, struct smb_request *req,
 	state->num_data = length;
 	state->max_read = max_read;
 
-	subreq = np_write_send(state, req->ev_ctx, state->handle,
+	subreq = np_write_send(state, req->sconn->ev_ctx, state->handle,
 			       state->data, length);
 	if (subreq == NULL) {
 		TALLOC_FREE(state);
@@ -330,7 +330,7 @@ static void api_dcerpc_cmd_write_done(struct tevent_req *subreq)
 		goto send;
 	}
 
-	subreq = np_read_send(state, req->ev_ctx,
+	subreq = np_read_send(state, req->sconn->ev_ctx,
 			      state->handle, state->data, state->max_read);
 	if (subreq == NULL) {
 		reply_nterror(req, NT_STATUS_NO_MEMORY);
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index a3df8a1b7363..bab9286751f5 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -2408,7 +2408,7 @@ static void defer_open(struct share_mode_lock *lck,
 	DBG_DEBUG("defering mid %" PRIu64 "\n", req->mid);
 
 	watch_req = dbwrap_watched_watch_send(watch_state,
-					      req->ev_ctx,
+					      req->sconn->ev_ctx,
 					      lck->data->record,
 					      (struct server_id){0});
 	if (watch_req == NULL) {
@@ -2416,7 +2416,7 @@ static void defer_open(struct share_mode_lock *lck,
 	}
 	tevent_req_set_callback(watch_req, defer_open_done, watch_state);
 
-	ok = tevent_req_set_endtime(watch_req, req->ev_ctx, abs_timeout);
+	ok = tevent_req_set_endtime(watch_req, req->sconn->ev_ctx, abs_timeout);
 	if (!ok) {
 		exit_server("tevent_req_set_endtime failed");
 	}
@@ -2508,7 +2508,7 @@ static void setup_kernel_oplock_poll_open(struct timeval request_time,
 	 * As this timer event is owned by req, it will
 	 * disappear if req it talloc_freed.
 	 */
-	open_rec->te = tevent_add_timer(req->ev_ctx,
+	open_rec->te = tevent_add_timer(req->sconn->ev_ctx,
 					req,
 					timeval_current_ofs(1, 0),
 					kernel_oplock_poll_open_timer,
@@ -2695,7 +2695,7 @@ static void schedule_async_open(struct timeval request_time,
 		exit_server("push_deferred_open_message_smb failed");
 	}
 
-	open_rec->te = tevent_add_timer(req->ev_ctx,
+	open_rec->te = tevent_add_timer(req->sconn->ev_ctx,
 					req,
 					timeval_current_ofs(20, 0),
 					schedule_async_open_timer,
diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c
index c945f0f61776..4be57bc2a5f0 100644
--- a/source3/smbd/pipes.c
+++ b/source3/smbd/pipes.c
@@ -67,7 +67,7 @@ NTSTATUS open_np_file(struct smb_request *smb_req, const char *name,
 			 conn->sconn->remote_address,
 			 conn->sconn->local_address,
 			 conn->session_info,
-			 smb_req->ev_ctx,
+			 conn->sconn->ev_ctx,
 			 conn->sconn->msg_ctx,
 			 &fsp->fake_file_handle);
 	if (!NT_STATUS_IS_OK(status)) {
@@ -206,7 +206,7 @@ void reply_pipe_write(struct smb_request *req)
 	DEBUG(6, ("reply_pipe_write: %s, name: %s len: %d\n", fsp_fnum_dbg(fsp),
 		  fsp_str_dbg(fsp), (int)state->numtowrite));
 
-	subreq = np_write_send(state, req->ev_ctx,
+	subreq = np_write_send(state, req->sconn->ev_ctx,
 			       fsp->fake_file_handle, data, state->numtowrite);
 	if (subreq == NULL) {
 		TALLOC_FREE(state);
@@ -322,7 +322,7 @@ void reply_pipe_write_and_X(struct smb_request *req)
 		state->numtowrite -= 2;
 	}
 
-	subreq = np_write_send(state, req->ev_ctx,
+	subreq = np_write_send(state, req->sconn->ev_ctx,
 			       fsp->fake_file_handle, data, state->numtowrite);
 	if (subreq == NULL) {
 		TALLOC_FREE(state);
@@ -435,7 +435,7 @@ void reply_pipe_read_and_X(struct smb_request *req)
 	state->outbuf = req->outbuf;
 	req->outbuf = NULL;
 
-	subreq = np_read_send(state, req->ev_ctx,
+	subreq = np_read_send(state, req->sconn->ev_ctx,
 			      fsp->fake_file_handle, data,
 			      state->smb_maxcnt);
 	if (subreq == NULL) {
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index e730676ef361..d2553049cd25 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -1506,8 +1506,6 @@ static connection_struct *switch_message(uint8_t type, struct smb_request *req)
 
 	errno = 0;
 
-	req->ev_ctx = NULL;
-
 	if (!xconn->smb1.negprot.done) {
 		switch (type) {
 			/*
@@ -1642,8 +1640,6 @@ static connection_struct *switch_message(uint8_t type, struct smb_request *req)
 			reply_nterror(req, NT_STATUS_ACCESS_DENIED);
 			return conn;
 		}
-
-		req->ev_ctx = conn->user_ev_ctx;
 	} else if (flags & AS_GUEST) {
 		/*
 		 * Does this protocol need to be run as guest? (Only archane
@@ -1653,13 +1649,9 @@ static connection_struct *switch_message(uint8_t type, struct smb_request *req)
 			reply_nterror(req, NT_STATUS_ACCESS_DENIED);
 			return conn;
 		}
-
-		req->ev_ctx = req->sconn->guest_ev_ctx;
 	} else {
 		/* This call needs to be run as root */
 		change_to_root_user();
-
-		req->ev_ctx = req->sconn->root_ev_ctx;
 	}
 
 	/* load service specific parameters */
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index f2617fab3b37..405bd6ce0046 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -5417,7 +5417,7 @@ void reply_close(struct smb_request *req)
 		 */
 
 		fsp->deferred_close = tevent_wait_send(
-			fsp, req->ev_ctx);
+			fsp, fsp->conn->sconn->ev_ctx);
 		if (fsp->deferred_close == NULL) {
 			status = NT_STATUS_NO_MEMORY;
 			goto done;
diff --git a/source3/smbd/smb2_break.c b/source3/smbd/smb2_break.c
index ec9c0f1376b7..ae6b9214b229 100644
--- a/source3/smbd/smb2_break.c
+++ b/source3/smbd/smb2_break.c
@@ -86,7 +86,7 @@ NTSTATUS smbd_smb2_request_process_break(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
 	}
 
-	subreq = smbd_smb2_oplock_break_send(req, req->ev_ctx,
+	subreq = smbd_smb2_oplock_break_send(req, req->sconn->ev_ctx,
 					     req, in_fsp, in_oplock_level);
 	if (subreq == NULL) {
 		return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
@@ -265,7 +265,7 @@ static NTSTATUS smbd_smb2_request_process_lease_break(
 	in_lease_key.data[1] = BVAL(inbody, 16);
 	in_lease_state = IVAL(inbody, 24);
 
-	subreq = smbd_smb2_lease_break_send(req, req->ev_ctx, req,
+	subreq = smbd_smb2_lease_break_send(req, req->sconn->ev_ctx, req,
 					    in_lease_key, in_lease_state);
 	if (subreq == NULL) {
 		return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
diff --git a/source3/smbd/smb2_close.c b/source3/smbd/smb2_close.c
index 1888736e4ae3..dea9512dfc6e 100644
--- a/source3/smbd/smb2_close.c
+++ b/source3/smbd/smb2_close.c
@@ -70,7 +70,7 @@ NTSTATUS smbd_smb2_request_process_close(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
 	}
 
-	subreq = smbd_smb2_close_send(req, req->ev_ctx,
+	subreq = smbd_smb2_close_send(req, req->sconn->ev_ctx,
 				      req, in_fsp, in_flags);
 	if (subreq == NULL) {
 		return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index fdd04ac0331f..9de7cef6f108 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -228,7 +228,7 @@ NTSTATUS smbd_smb2_request_process_create(struct smbd_smb2_request *smb2req)
 	}
 
 	tsubreq = smbd_smb2_create_send(smb2req,
-				       smb2req->ev_ctx,
+				       smb2req->sconn->ev_ctx,
 				       smb2req,
 				       in_oplock_level,
 				       in_impersonation_level,
@@ -1759,7 +1759,7 @@ bool schedule_deferred_open_message_smb2(
 		(unsigned long long)mid ));
 
 	tevent_schedule_immediate(state->im,
-			smb2req->ev_ctx,
+			smb2req->sconn->ev_ctx,
 			smbd_smb2_create_request_dispatch_immediate,
 			smb2req);
 
@@ -1791,7 +1791,7 @@ static bool smbd_smb2_create_cancel(struct tevent_req *req)
 
 	remove_deferred_open_message_smb2_internal(smb2req, mid);
 
-	tevent_req_defer_callback(req, smb2req->ev_ctx);
+	tevent_req_defer_callback(req, smb2req->sconn->ev_ctx);
 	tevent_req_nterror(req, NT_STATUS_CANCELLED);
 	return true;
 }
diff --git a/source3/smbd/smb2_flush.c b/source3/smbd/smb2_flush.c
index 4f815a6f5b0c..470a8df49442 100644
--- a/source3/smbd/smb2_flush.c
+++ b/source3/smbd/smb2_flush.c
@@ -58,7 +58,7 @@ NTSTATUS smbd_smb2_request_process_flush(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
 	}
 
-	subreq = smbd_smb2_flush_send(req, req->ev_ctx,
+	subreq = smbd_smb2_flush_send(req, req->sconn->ev_ctx,
 				      req, in_fsp);
 	if (subreq == NULL) {
 		return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
diff --git a/source3/smbd/smb2_getinfo.c b/source3/smbd/smb2_getinfo.c
index 314f44e858cf..29625fc1ba70 100644
--- a/source3/smbd/smb2_getinfo.c
+++ b/source3/smbd/smb2_getinfo.c
@@ -122,7 +122,7 @@ NTSTATUS smbd_smb2_request_process_getinfo(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
 	}
 
-	subreq = smbd_smb2_getinfo_send(req, req->ev_ctx,
+	subreq = smbd_smb2_getinfo_send(req, req->sconn->ev_ctx,
 					req, in_fsp,
 					in_info_type,
 					in_file_info_class,
diff --git a/source3/smbd/smb2_glue.c b/source3/smbd/smb2_glue.c
index cccc763c3425..6a73ec050e24 100644
--- a/source3/smbd/smb2_glue.c
+++ b/source3/smbd/smb2_glue.c
@@ -46,7 +46,6 @@ struct smb_request *smbd_smb2_fake_smb_request(struct smbd_smb2_request *req)
 	smbreq->conn = req->tcon->compat;
 	smbreq->sconn = req->sconn;
 	smbreq->xconn = req->xconn;
-	smbreq->ev_ctx = req->ev_ctx;
 	smbreq->smbpid = (uint16_t)IVAL(inhdr, SMB2_HDR_PID);
 	smbreq->flags2 = FLAGS2_UNICODE_STRINGS |
 			 FLAGS2_32_BIT_ERROR_CODES |
diff --git a/source3/smbd/smb2_ioctl.c b/source3/smbd/smb2_ioctl.c
index 451733c1a659..be70e3a09128 100644
--- a/source3/smbd/smb2_ioctl.c
+++ b/source3/smbd/smb2_ioctl.c
@@ -217,7 +217,7 @@ NTSTATUS smbd_smb2_request_process_ioctl(struct smbd_smb2_request *req)
 		break;
 	}
 
-	subreq = smbd_smb2_ioctl_send(req, req->ev_ctx,
+	subreq = smbd_smb2_ioctl_send(req, req->sconn->ev_ctx,
 				      req, in_fsp,
 				      in_ctl_code,
 				      in_input_buffer,
diff --git a/source3/smbd/smb2_ioctl_named_pipe.c b/source3/smbd/smb2_ioctl_named_pipe.c
index f8012ae19203..f9e3dec049c0 100644
--- a/source3/smbd/smb2_ioctl_named_pipe.c
+++ b/source3/smbd/smb2_ioctl_named_pipe.c
@@ -143,7 +143,7 @@ static void smbd_smb2_ioctl_pipe_write_done(struct tevent_req *subreq)
 		(unsigned int)state->out_output.length ));
 
 	subreq = np_read_send(state->smbreq->conn,
-			      state->smb2req->ev_ctx,
+			      state->smb2req->sconn->ev_ctx,
 			      state->fsp->fake_file_handle,
 			      state->out_output.data,
 			      state->out_output.length);
diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c
index da5a54df6233..3cc591089a42 100644
--- a/source3/smbd/smb2_lock.c
+++ b/source3/smbd/smb2_lock.c
@@ -134,7 +134,7 @@ NTSTATUS smbd_smb2_request_process_lock(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
 	}
 
-	subreq = smbd_smb2_lock_send(req, req->ev_ctx,
+	subreq = smbd_smb2_lock_send(req, req->sconn->ev_ctx,
 				     req, in_fsp,
 				     in_lock_count,
 				     in_locks);
@@ -368,7 +368,7 @@ static struct tevent_req *smbd_smb2_lock_send(TALLOC_CTX *mem_ctx,
 	}
 
 	if (async) {
-		tevent_req_defer_callback(req, smb2req->ev_ctx);
+		tevent_req_defer_callback(req, smb2req->sconn->ev_ctx);
 		SMBPROFILE_IOBYTES_ASYNC_SET_IDLE(smb2req->profile);
 		return req;
 	}
diff --git a/source3/smbd/smb2_notify.c b/source3/smbd/smb2_notify.c
index e49e76d96413..242415625567 100644
--- a/source3/smbd/smb2_notify.c
+++ b/source3/smbd/smb2_notify.c
@@ -94,7 +94,7 @@ NTSTATUS smbd_smb2_request_process_notify(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
 	}
 
-	subreq = smbd_smb2_notify_send(req, req->ev_ctx,
+	subreq = smbd_smb2_notify_send(req, req->sconn->ev_ctx,
 				       req, in_fsp,
 				       in_flags,
 				       in_output_buffer_length,
@@ -355,7 +355,7 @@ static void smbd_smb2_notify_reply(struct smb_request *smbreq,
 		}
 	}
 
-	tevent_req_defer_callback(req, state->smb2req->ev_ctx);
+	tevent_req_defer_callback(req, state->smb2req->sconn->ev_ctx);
 
 	if (!NT_STATUS_IS_OK(state->status)) {
 		tevent_req_nterror(req, state->status);
diff --git a/source3/smbd/smb2_query_directory.c b/source3/smbd/smb2_query_directory.c
index ab6c3dc788ee..a80c9f596770 100644
--- a/source3/smbd/smb2_query_directory.c
+++ b/source3/smbd/smb2_query_directory.c
@@ -125,7 +125,7 @@ NTSTATUS smbd_smb2_request_process_query_directory(struct smbd_smb2_request *req
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
 	}
 
-	subreq = smbd_smb2_query_directory_send(req, req->ev_ctx,
+	subreq = smbd_smb2_query_directory_send(req, req->sconn->ev_ctx,
 				     req, in_fsp,
 				     in_file_info_class,
 				     in_flags,
diff --git a/source3/smbd/smb2_read.c b/source3/smbd/smb2_read.c
index 065a5cd5fc69..a7d2496bc6f3 100644
--- a/source3/smbd/smb2_read.c
+++ b/source3/smbd/smb2_read.c
@@ -97,7 +97,7 @@ NTSTATUS smbd_smb2_request_process_read(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
 	}
 
-	subreq = smbd_smb2_read_send(req, req->ev_ctx,
+	subreq = smbd_smb2_read_send(req, req->sconn->ev_ctx,
 				     req, in_fsp,
 				     in_flags,
 				     in_length,
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index e36db1e55f5e..1e9ed331aa6a 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2620,10 +2620,8 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
 		SMB_ASSERT(call->fileid_ofs == 0);
 		/* This call needs to be run as root */
 		change_to_root_user();
-		req->ev_ctx = req->sconn->root_ev_ctx;
 	} else {
 		SMB_ASSERT(call->need_tcon);
-		req->ev_ctx = req->tcon->compat->user_ev_ctx;
 	}
 
 #define _INBYTES(_r) \
diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c
index 5420d4f09bbd..2c24e7a1abcb 100644
--- a/source3/smbd/smb2_sesssetup.c
+++ b/source3/smbd/smb2_sesssetup.c
@@ -95,7 +95,7 @@ NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req)
 	in_security_buffer.length = in_security_length;
 
 	subreq = smbd_smb2_session_setup_wrap_send(smb2req,
-						   smb2req->ev_ctx,
+						   smb2req->sconn->ev_ctx,
 						   smb2req,
 						   in_session_id,
 						   in_flags,
@@ -1218,7 +1218,7 @@ NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, status);
 	}
 
-	subreq = smbd_smb2_logoff_send(req, req->ev_ctx, req);
+	subreq = smbd_smb2_logoff_send(req, req->sconn->ev_ctx, req);
 	if (subreq == NULL) {
 		return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
 	}
diff --git a/source3/smbd/smb2_setinfo.c b/source3/smbd/smb2_setinfo.c
index 7c1f84bd79de..b19cbb150a7f 100644
--- a/source3/smbd/smb2_setinfo.c
+++ b/source3/smbd/smb2_setinfo.c
@@ -108,7 +108,7 @@ NTSTATUS smbd_smb2_request_process_setinfo(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
 	}
 
-	subreq = smbd_smb2_setinfo_send(req, req->ev_ctx,
+	subreq = smbd_smb2_setinfo_send(req, req->sconn->ev_ctx,
 					req, in_fsp,
 					in_info_type,
 					in_file_info_class,
diff --git a/source3/smbd/smb2_tcon.c b/source3/smbd/smb2_tcon.c
index 3a4a15d3059e..ebd31602efcd 100644
--- a/source3/smbd/smb2_tcon.c
+++ b/source3/smbd/smb2_tcon.c
@@ -94,7 +94,7 @@ NTSTATUS smbd_smb2_request_process_tcon(struct smbd_smb2_request *req)
 	}
 
 	subreq = smbd_smb2_tree_connect_send(req,
-					     req->ev_ctx,
+					     req->sconn->ev_ctx,
 					     req,
 					     in_path_string);
 	if (subreq == NULL) {
@@ -491,7 +491,7 @@ NTSTATUS smbd_smb2_request_process_tdis(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, status);
 	}
 
-	subreq = smbd_smb2_tdis_send(req, req->ev_ctx, req);
+	subreq = smbd_smb2_tdis_send(req, req->sconn->ev_ctx, req);
 	if (subreq == NULL) {
 		return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
 	}
diff --git a/source3/smbd/smb2_write.c b/source3/smbd/smb2_write.c
index d5ab12ecc21a..ee95bd317aef 100644
--- a/source3/smbd/smb2_write.c
+++ b/source3/smbd/smb2_write.c
@@ -109,7 +109,7 @@ NTSTATUS smbd_smb2_request_process_write(struct smbd_smb2_request *req)
 		return smbd_smb2_request_error(req, NT_STATUS_FILE_CLOSED);
 	}
 
-	subreq = smbd_smb2_write_send(req, req->ev_ctx,
+	subreq = smbd_smb2_write_send(req, req->sconn->ev_ctx,
 				      req, in_fsp,
 				      in_data_buffer,
 				      in_offset,
-- 
2.17.1


From 08aaaa93793b98293c09e8c407a738ff29b6fb17 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:19:20 +0100
Subject: [PATCH 46/66] Revert "smbd: add an effective
 connection_struct->user_ev_ctx that holds the event context used for the
 current user"

This reverts commit f2df8be16be9dccd3d10ec060f1efbe5007a28c6.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/include/vfs.h             | 2 --
 source3/modules/vfs_aio_pthread.c | 2 +-
 source3/modules/vfs_default.c     | 2 +-
 source3/modules/vfs_readonly.c    | 1 -
 source3/smbd/conn.c               | 7 -------
 source3/smbd/msdfs.c              | 2 --
 source3/smbd/uid.c                | 6 ------
 7 files changed, 2 insertions(+), 20 deletions(-)

diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index 1a05283fe6cc..8c35fa5ecc7a 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -402,7 +402,6 @@ typedef struct files_struct {
 
 struct vuid_cache_entry {
 	struct auth_session_info *session_info;
-	struct tevent_context *user_ev_ctx;
 	uint64_t vuid; /* SMB2 compat */
 	bool read_only;
 	uint32_t share_access;
@@ -450,7 +449,6 @@ typedef struct connection_struct {
 	 * on the vuid using this tid, this might change per SMB request.
 	 */
 	struct auth_session_info *session_info;
-	struct tevent_context *user_ev_ctx;
 
 	/*
 	 * If the "force group" parameter is set, this is the primary gid that
diff --git a/source3/modules/vfs_aio_pthread.c b/source3/modules/vfs_aio_pthread.c
index c1d1a7d518a6..cb90b12d4b29 100644
--- a/source3/modules/vfs_aio_pthread.c
+++ b/source3/modules/vfs_aio_pthread.c
@@ -276,7 +276,7 @@ static int open_async(const files_struct *fsp,
 	}
 
 	subreq = pthreadpool_tevent_job_send(opd,
-					     fsp->conn->user_ev_ctx,
+					     fsp->conn->sconn->ev_ctx,
 					     fsp->conn->sconn->pool,
 					     aio_open_worker, opd);
 	if (subreq == NULL) {
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 1734361fca95..256f173aec5f 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -1844,7 +1844,7 @@ static struct tevent_req *vfswrap_offload_write_send(
 		return tevent_req_post(req, ev);
 	}
 
-	state->src_ev = src_fsp->conn->user_ev_ctx;
+	state->src_ev = src_fsp->conn->sconn->ev_ctx;
 	state->src_fsp = src_fsp;
 
 	state->buf = talloc_array(state, uint8_t, num);
diff --git a/source3/modules/vfs_readonly.c b/source3/modules/vfs_readonly.c
index 570eb7c4d15a..cde8ef973ca1 100644
--- a/source3/modules/vfs_readonly.c
+++ b/source3/modules/vfs_readonly.c
@@ -84,7 +84,6 @@ static int readonly_connect(vfs_handle_struct *handle,
       for (i=0; i< VUID_CACHE_SIZE; i++) {
         struct vuid_cache_entry *ent = &conn->vuid_cache->array[i];
         ent->vuid = UID_FIELD_INVALID;
-        ent->user_ev_ctx = NULL;
         TALLOC_FREE(ent->session_info);
         ent->read_only = false;
         ent->share_access = 0;
diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c
index 3b9aaac7834b..8f472c0d2458 100644
--- a/source3/smbd/conn.c
+++ b/source3/smbd/conn.c
@@ -94,12 +94,6 @@ static void conn_clear_vuid_cache(connection_struct *conn, uint64_t vuid)
 
 		if (ent->vuid == vuid) {
 			ent->vuid = UID_FIELD_INVALID;
-
-			if (conn->user_ev_ctx == ent->user_ev_ctx) {
-				conn->user_ev_ctx = NULL;
-			}
-			ent->user_ev_ctx = NULL;
-
 			/*
 			 * We need to keep conn->session_info around
 			 * if it's equal to ent->session_info as a SMBulogoff
@@ -123,7 +117,6 @@ static void conn_clear_vuid_cache(connection_struct *conn, uint64_t vuid)
 			} else {
 				TALLOC_FREE(ent->session_info);
 			}
-
 			ent->read_only = False;
 			ent->share_access = 0;
 		}
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index c523abb3158c..65e95128aa20 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -320,8 +320,6 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx,
 		vfs_user = get_current_username();
 	}
 
-	conn->user_ev_ctx = sconn->raw_ev_ctx;
-
 	set_conn_connectpath(conn, connpath);
 
 	/*
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index f902f2aeae38..7aecea5f857a 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -78,7 +78,6 @@ static void free_conn_session_info_if_unused(connection_struct *conn)
 		}
 	}
 	/* Not used, safe to free. */
-	conn->user_ev_ctx = NULL;
 	TALLOC_FREE(conn->session_info);
 }
 
@@ -204,7 +203,6 @@ static bool check_user_ok(connection_struct *conn,
 			}
 			free_conn_session_info_if_unused(conn);
 			conn->session_info = ent->session_info;
-			conn->user_ev_ctx = ent->user_ev_ctx;
 			conn->read_only = ent->read_only;
 			conn->share_access = ent->share_access;
 			conn->vuid = ent->vuid;
@@ -253,8 +251,6 @@ static bool check_user_ok(connection_struct *conn,
 		ent->session_info->unix_token->uid = sec_initial_uid();
 	}
 
-	ent->user_ev_ctx = conn->sconn->raw_ev_ctx;
-
 	/*
 	 * It's actually OK to call check_user_ok() with
 	 * vuid == UID_FIELD_INVALID as called from change_to_user_by_session().
@@ -267,7 +263,6 @@ static bool check_user_ok(connection_struct *conn,
 	free_conn_session_info_if_unused(conn);
 	conn->session_info = ent->session_info;
 	conn->vuid = ent->vuid;
-	conn->user_ev_ctx = ent->user_ev_ctx;
 	if (vuid == UID_FIELD_INVALID) {
 		/*
 		 * Not strictly needed, just make it really
@@ -276,7 +271,6 @@ static bool check_user_ok(connection_struct *conn,
 		ent->read_only = false;
 		ent->share_access = 0;
 		ent->session_info = NULL;
-		ent->user_ev_ctx = NULL;
 	}
 
 	conn->read_only = readonly_share;
-- 
2.17.1


From a02c97be832da2939ff1ccf4db6ed6235f448958 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:20:54 +0100
Subject: [PATCH 47/66] Revert "smbd: use sconn->root_ev_ctx for
 smbd_sig_{term,hup}_handler()"

This reverts commit c835ffa72ddfd2431d22909148913b50f0d829d1.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/process.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index d2553049cd25..2363eb78ea52 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -977,7 +977,7 @@ static void smbd_setup_sig_term_handler(struct smbd_server_connection *sconn)
 {
 	struct tevent_signal *se;
 
-	se = tevent_add_signal(sconn->root_ev_ctx,
+	se = tevent_add_signal(sconn->ev_ctx,
 			       sconn,
 			       SIGTERM, 0,
 			       smbd_sig_term_handler,
@@ -1007,7 +1007,7 @@ static void smbd_setup_sig_hup_handler(struct smbd_server_connection *sconn)
 {
 	struct tevent_signal *se;
 
-	se = tevent_add_signal(sconn->root_ev_ctx,
+	se = tevent_add_signal(sconn->ev_ctx,
 			       sconn,
 			       SIGHUP, 0,
 			       smbd_sig_hup_handler,
-- 
2.17.1


From 97416110d4b9f1c8ff0bb19806aab7ab87e048de Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:20:58 +0100
Subject: [PATCH 48/66] Revert "smbd: use sconn->root_ev_ctx for
 brl_timeout_fn()"

This reverts commit 182991c26c8149c79b13a277b9822efc49fd1df0.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/blocking.c  | 6 +-----
 source3/smbd/smb2_lock.c | 6 +-----
 2 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c
index c281aae619de..6cbf5c03e932 100644
--- a/source3/smbd/blocking.c
+++ b/source3/smbd/blocking.c
@@ -135,11 +135,7 @@ static bool recalc_brl_timeout(struct smbd_server_connection *sconn)
 		    (int)from_now.tv_sec, (int)from_now.tv_usec));
 	}
 
-	/*
-	 * brl_timeout_fn() calls change_to_root_user()
-	 * so we can use sconn->root_ev_ctx.
-	 */
-	sconn->smb1.locks.brl_timeout = tevent_add_timer(sconn->root_ev_ctx,
+	sconn->smb1.locks.brl_timeout = tevent_add_timer(sconn->ev_ctx,
 							 NULL, next_timeout,
 							 brl_timeout_fn, sconn);
 	if (sconn->smb1.locks.brl_timeout == NULL) {
diff --git a/source3/smbd/smb2_lock.c b/source3/smbd/smb2_lock.c
index 3cc591089a42..a05470e52e4a 100644
--- a/source3/smbd/smb2_lock.c
+++ b/source3/smbd/smb2_lock.c
@@ -568,12 +568,8 @@ static bool recalc_smb2_brl_timeout(struct smbd_server_connection *sconn)
 			(int)from_now.tv_sec, (int)from_now.tv_usec));
 	}
 
-	/*
-	 * brl_timeout_fn() calls change_to_root_user()
-	 * so we can use sconn->root_ev_ctx.
-	 */
 	sconn->smb2.locks.brl_timeout = tevent_add_timer(
-				sconn->root_ev_ctx,
+				sconn->ev_ctx,
 				NULL,
 				next_timeout,
 				brl_timeout_fn,
-- 
2.17.1


From cd24a2e9a48a8ce21b340771332d0d40cdbb81ac Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:21:01 +0100
Subject: [PATCH 49/66] Revert "smbd: add
 smbd_server_connection->{root,guest}_ev_ctx pointer"

This reverts commit 146938217ed1ab9a7a9f38c055fec5513cbd5c4d.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/globals.h | 2 --
 source3/smbd/msdfs.c   | 2 --
 source3/smbd/process.c | 2 --
 3 files changed, 6 deletions(-)

diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index a273cdb3651e..689aa0b6ed1e 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -878,8 +878,6 @@ struct smbd_server_connection {
 	const char *remote_hostname;
 	struct tevent_context *ev_ctx;
 	struct tevent_context *raw_ev_ctx;
-	struct tevent_context *root_ev_ctx;
-	struct tevent_context *guest_ev_ctx;
 	struct messaging_context *msg_ctx;
 	struct notify_context *notify_ctx;
 	bool using_smb2;
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index 65e95128aa20..af5888c8a24c 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -265,8 +265,6 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx,
 	}
 
 	sconn->ev_ctx = sconn->raw_ev_ctx;
-	sconn->root_ev_ctx = sconn->raw_ev_ctx;
-	sconn->guest_ev_ctx = sconn->raw_ev_ctx;
 	sconn->msg_ctx = msg;
 
 	conn = conn_new(sconn);
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 2363eb78ea52..dbcf13187cf2 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -3925,8 +3925,6 @@ void smbd_process(struct tevent_context *ev_ctx,
 
 	sconn->ev_ctx = ev_ctx;
 	sconn->raw_ev_ctx = ev_ctx;
-	sconn->root_ev_ctx = ev_ctx;
-	sconn->guest_ev_ctx = ev_ctx;
 	sconn->msg_ctx = msg_ctx;
 
 	ret = pthreadpool_tevent_init(sconn, lp_aio_max_threads(),
-- 
2.17.1


From 279148606e0b99a005d460d45001f34b93d5396d Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:21:04 +0100
Subject: [PATCH 50/66] Revert "smbd: use raw_ev_ctx to clear the
 MSG_SMB_CONF_UPDATED registration"

This reverts commit f5f9b719741465c7be3de20a6a69ec106ecc4568.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/process.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index dbcf13187cf2..03aa2254c156 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -4063,7 +4063,7 @@ void smbd_process(struct tevent_context *ev_ctx,
 			   ID_CACHE_KILL, smbd_id_cache_kill);
 
 	messaging_deregister(sconn->msg_ctx,
-			     MSG_SMB_CONF_UPDATED, sconn->raw_ev_ctx);
+			     MSG_SMB_CONF_UPDATED, sconn->ev_ctx);
 	messaging_register(sconn->msg_ctx, sconn,
 			   MSG_SMB_CONF_UPDATED, smbd_conf_updated);
 
-- 
2.17.1


From f4b26aeea0afeba9ff476d97086ee6a4e3899339 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:21:06 +0100
Subject: [PATCH 51/66] Revert "smbd: explain that/why we use the raw
 tevent_context for linux_oplock_signal_handler()"

This reverts commit dc517b20f60a156d73fdd551557eb1d4366dfdeb.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/oplock_linux.c | 14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c
index 76760ff0346f..9292a3370e56 100644
--- a/source3/smbd/oplock_linux.c
+++ b/source3/smbd/oplock_linux.c
@@ -125,12 +125,6 @@ static void linux_oplock_signal_handler(struct tevent_context *ev_ctx,
 	int fd = info->si_fd;
 	files_struct *fsp;
 
-	/*
-	 * This function doesn't expect any specific impersonation, as it only
-	 * sends messages to other smbd processes. And messaging_send_iov_from()
-	 * already handles EACCES.
-	 */
-
 	fsp = file_find_fd(sconn, fd);
 	if (fsp == NULL) {
 		DEBUG(0,("linux_oplock_signal_handler: failed to find fsp for file fd=%d (file was closed ?)\n", fd ));
@@ -241,13 +235,7 @@ struct kernel_oplocks *linux_init_kernel_oplocks(struct smbd_server_connection *
 	ctx->ops = &linux_koplocks;
 	ctx->private_data = sconn;
 
-	/*
-	 * linux_oplock_signal_handler() only
-	 * sends messages to other smbd processes
-	 * and doesn't require any impersonation.
-	 * So we can just use the raw tevent_context.
-	 */
-	se = tevent_add_signal(sconn->raw_ev_ctx,
+	se = tevent_add_signal(sconn->ev_ctx,
 			       ctx,
 			       RT_SIGNAL_LEASE, SA_SIGINFO,
 			       linux_oplock_signal_handler,
-- 
2.17.1


From 08108b82de4cd52c6dd2223c58aafe3fe7797117 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:23:43 +0100
Subject: [PATCH 52/66] Revert "smbd: explain that/why we use the raw
 tevent_context for do_break_to_none()"

This reverts commit 1d5210b615035e46b90758ac7aa4ceec9174bee5.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/oplock.c | 15 +--------------
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index d733bec2d266..3feddaa90b87 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -1236,15 +1236,7 @@ static void contend_level2_oplocks_begin_default(files_struct *fsp,
 		TALLOC_FREE(state);
 		return;
 	}
-
-	/*
-	 * do_break_to_none() only operates on the
-	 * locking.tdb and sends network packets to
-	 * the client. That doesn't require any
-	 * impersonation, so we just use the
-	 * raw tevent context here.
-	 */
-	tevent_schedule_immediate(im, sconn->raw_ev_ctx, do_break_to_none, state);
+	tevent_schedule_immediate(im, sconn->ev_ctx, do_break_to_none, state);
 }
 
 static void send_break_to_none(struct messaging_context *msg_ctx,
@@ -1271,11 +1263,6 @@ static void do_break_to_none(struct tevent_context *ctx,
 	struct share_mode_lock *lck;
 	struct share_mode_data *d;
 
-	/*
-	 * Note this function doesn't run under any specific impersonation and
-	 * is not expected to call any SMB_VFS operation!
-	 */
-
 	lck = get_existing_share_mode_lock(talloc_tos(), state->id);
 	if (lck == NULL) {
 		DEBUG(1, ("%s: failed to lock share mode entry for file %s.\n",
-- 
2.17.1


From b3761940bd584f444e2629e6d6631b3564658437 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:23:52 +0100
Subject: [PATCH 53/66] Revert "smbd: explain that/why we use the raw
 tevent_context for oplock_timeout_handler()"

This reverts commit e73eaa3c8004d3d8aff316cdb26b0bef85eceaca.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/oplock.c | 14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 3feddaa90b87..64ca0d175857 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -817,11 +817,6 @@ static void oplock_timeout_handler(struct tevent_context *ctx,
 {
 	files_struct *fsp = (files_struct *)private_data;
 
-	/*
-	 * Note this function doesn't run under any specific impersonation and
-	 * is not expected to call any SMB_VFS operation!
-	 */
-
 	SMB_ASSERT(fsp->sent_oplock_break != NO_BREAK_SENT);
 
 	/* Remove the timed event handler. */
@@ -842,15 +837,8 @@ static void add_oplock_timeout_handler(files_struct *fsp)
 			  "around\n"));
 	}
 
-	/*
-	 * For now we keep the logic and use the
-	 * raw event context. We're called from
-	 * the messaging system from a raw event context.
-	 * Also oplock_timeout_handler doesn't invoke
-	 * SMB_VFS calls.
-	 */
 	fsp->oplock_timeout =
-		tevent_add_timer(fsp->conn->sconn->raw_ev_ctx, fsp,
+		tevent_add_timer(fsp->conn->sconn->ev_ctx, fsp,
 				 timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0),
 				 oplock_timeout_handler, fsp);
 
-- 
2.17.1


From 23d170c5f66664616b87e7256de698c8d21d155e Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:24:37 +0100
Subject: [PATCH 54/66] Revert "smbd: explain that/why we use the raw
 tevent_context for lease_timeout_handler()"

This reverts commit 52f098d38da72d6eff3c4cac61487da897a8651c.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/oplock.c | 12 +-----------
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 64ca0d175857..31a36304310f 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -354,11 +354,6 @@ static void lease_timeout_handler(struct tevent_context *ctx,
 	struct share_mode_lock *lck;
 	uint16_t old_epoch = lease->lease.lease_epoch;
 
-	/*
-	 * This function runs without any specific impersonation
-	 * and must not call any SMB_VFS operations!
-	 */
-
 	fsp = file_find_one_fsp_from_lease_key(lease->sconn,
 					       &lease->lease.lease_key);
 	if (fsp == NULL) {
@@ -454,12 +449,7 @@ bool fsp_lease_update(struct share_mode_lock *lck,
 
 			DEBUG(10,("%s: setup timeout handler\n", __func__));
 
-			/*
-			 * lease_timeout_handler() only accesses locking.tdb
-			 * so we don't use any impersonation and use
-			 * the raw tevent context.
-			 */
-			lease->timeout = tevent_add_timer(lease->sconn->raw_ev_ctx,
+			lease->timeout = tevent_add_timer(lease->sconn->ev_ctx,
 							  lease, t,
 							  lease_timeout_handler,
 							  lease);
-- 
2.17.1


From 068d575c7998dd3d75e58e3796cc1b76af9d7d4c Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:26:03 +0100
Subject: [PATCH 55/66] Revert "smbd: explain that/why we use the raw
 tevent_context for update_write_time_handler()"

This reverts commit 7cfafaf190643eb28fc95d21a02a4e5e529e16d1.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/fileio.c | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index 1fe806e058d2..cde6a057ccda 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -232,17 +232,9 @@ void trigger_write_time_update(struct files_struct *fsp)
 	DEBUG(5, ("Update write time %d usec later on %s\n",
 		  delay, fsp_str_dbg(fsp)));
 
-	/*
-	 * trigger the update 2 seconds later
-	 *
-	 * Note that update_write_time_handler()
-	 * => fsp_flush_write_time_update()
-	 * won't do any SMB_VFS calls and don't
-	 * need impersonation. So we use the
-	 * raw event context for this.
-	 */
+	/* trigger the update 2 seconds later */
 	fsp->update_write_time_event =
-		tevent_add_timer(fsp->conn->sconn->raw_ev_ctx, NULL,
+		tevent_add_timer(fsp->conn->sconn->ev_ctx, NULL,
 				 timeval_current_ofs_usec(delay),
 				 update_write_time_handler, fsp);
 }
-- 
2.17.1


From 8e04b52d04dc56f95cb5ba2f23f2b254df5db2e5 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:26:08 +0100
Subject: [PATCH 56/66] Revert "vfs_glusterfs: explain that/why we use the raw
 tevent_context in init_gluster_aio()"

This reverts commit b0af5715b0a7592a9728e0b76f653b9ab6228708.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/modules/vfs_glusterfs.c | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
index 9b623a4658b7..c9d57b4b6463 100644
--- a/source3/modules/vfs_glusterfs.c
+++ b/source3/modules/vfs_glusterfs.c
@@ -766,16 +766,7 @@ static bool init_gluster_aio(struct vfs_handle_struct *handle)
 	read_fd = fds[0];
 	write_fd = fds[1];
 
-	/*
-	 * We use the raw tevent context here,
-	 * as this is a global event handler.
-	 *
-	 * The tevent_req_defer_callback()
-	 * calls will make sure the results
-	 * of async calls are propagated
-	 * to the correct tevent_context.
-	 */
-	aio_read_event = tevent_add_fd(handle->conn->sconn->raw_ev_ctx,
+	aio_read_event = tevent_add_fd(handle->conn->sconn->ev_ctx,
 					NULL,
 					read_fd,
 					TEVENT_FD_READ,
-- 
2.17.1


From dceaa25d15077cc1856b9b747045d02299caf803 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 28 Dec 2018 13:25:57 +0100
Subject: [PATCH 57/66] s3:smbd: use passed in ev in
 smbd_smb2_query_directory_send()

The ev argument is also a raw ev.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/smb2_query_directory.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source3/smbd/smb2_query_directory.c b/source3/smbd/smb2_query_directory.c
index a80c9f596770..6020025b28b7 100644
--- a/source3/smbd/smb2_query_directory.c
+++ b/source3/smbd/smb2_query_directory.c
@@ -275,7 +275,7 @@ static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx,
 	if (req == NULL) {
 		return NULL;
 	}
-	state->ev = fsp->conn->sconn->raw_ev_ctx;
+	state->ev = ev;
 	state->fsp = fsp;
 	state->smb2req = smb2req;
 	state->in_output_buffer_length = in_output_buffer_length;
-- 
2.17.1


From 3878011a0c4dc0a6fe59dd356d6a41ac9f17c1ee Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 7 Jan 2019 21:10:19 +0100
Subject: [PATCH 58/66] s3:smbd: don't use async dosmode if per-thread cwd is
 not available

The additional overhead for the async processing should be avoided when
we know the lower level has to fallback to sync processing anyway.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/smb2_query_directory.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/source3/smbd/smb2_query_directory.c b/source3/smbd/smb2_query_directory.c
index 6020025b28b7..fdb87188f933 100644
--- a/source3/smbd/smb2_query_directory.c
+++ b/source3/smbd/smb2_query_directory.c
@@ -516,6 +516,9 @@ static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx,
 		size_t max_threads;
 
 		max_threads = pthreadpool_tevent_max_threads(conn->sconn->pool);
+		if (max_threads == 0 || !per_thread_cwd_supported()) {
+			state->async_dosmode = false;
+		}
 
 		state->max_async_dosmode_active = lp_smbd_max_async_dosmode(
 							SNUM(conn));
-- 
2.17.1


From 704ae16b2f5f2d569c5bc984b4f6eb6f9fcddb21 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 8 Jan 2019 07:38:04 +0100
Subject: [PATCH 59/66] vfs_default: add sync fallback to pread_send/recv

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/modules/vfs_default.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 256f173aec5f..4ca7578cc538 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -742,8 +742,18 @@ static void vfs_pread_done(struct tevent_req *subreq)
 	TALLOC_FREE(subreq);
 	SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
 	talloc_set_destructor(state, NULL);
-	if (tevent_req_error(req, ret)) {
-		return;
+	if (ret != 0) {
+		if (ret != EAGAIN) {
+			tevent_req_error(req, ret);
+			return;
+		}
+		/*
+		 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
+		 * means the lower level pthreadpool failed to create a new
+		 * thread. Fallback to sync processing in that case to allow
+		 * some progress for the client.
+		 */
+		vfs_pread_do(state);
 	}
 
 	tevent_req_done(req);
-- 
2.17.1


From d70a611eef2d2ceb721ffe39038feec358db759b Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 8 Jan 2019 07:38:42 +0100
Subject: [PATCH 60/66] vfs_default: add sync fallback to pwrite_send/recv

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/modules/vfs_default.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 4ca7578cc538..57ce0b465ece 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -870,8 +870,18 @@ static void vfs_pwrite_done(struct tevent_req *subreq)
 	TALLOC_FREE(subreq);
 	SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
 	talloc_set_destructor(state, NULL);
-	if (tevent_req_error(req, ret)) {
-		return;
+	if (ret != 0) {
+		if (ret != EAGAIN) {
+			tevent_req_error(req, ret);
+			return;
+		}
+		/*
+		 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
+		 * means the lower level pthreadpool failed to create a new
+		 * thread. Fallback to sync processing in that case to allow
+		 * some progress for the client.
+		 */
+		vfs_pwrite_do(state);
 	}
 
 	tevent_req_done(req);
-- 
2.17.1


From 30e29b3dac6569e0f1245ae0b05e09b654d84e54 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 8 Jan 2019 07:38:53 +0100
Subject: [PATCH 61/66] vfs_default: add sync fallback to fsync_send/recv

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/modules/vfs_default.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 57ce0b465ece..8d40cd64540a 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -988,8 +988,18 @@ static void vfs_fsync_done(struct tevent_req *subreq)
 	TALLOC_FREE(subreq);
 	SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
 	talloc_set_destructor(state, NULL);
-	if (tevent_req_error(req, ret)) {
-		return;
+	if (ret != 0) {
+		if (ret != EAGAIN) {
+			tevent_req_error(req, ret);
+			return;
+		}
+		/*
+		 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
+		 * means the lower level pthreadpool failed to create a new
+		 * thread. Fallback to sync processing in that case to allow
+		 * some progress for the client.
+		 */
+		vfs_fsync_do(state);
 	}
 
 	tevent_req_done(req);
-- 
2.17.1


From 9db0f0d3d20973a94d4e6e071866b4fd59f3d4fd Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 8 Jan 2019 10:32:16 +0100
Subject: [PATCH 62/66] vfs_aio_pthread: use struct initializer for
 aio_open_private_data

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/modules/vfs_aio_pthread.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/source3/modules/vfs_aio_pthread.c b/source3/modules/vfs_aio_pthread.c
index cb90b12d4b29..be74e77b4335 100644
--- a/source3/modules/vfs_aio_pthread.c
+++ b/source3/modules/vfs_aio_pthread.c
@@ -209,15 +209,17 @@ static struct aio_open_private_data *create_private_open_data(const files_struct
 		return NULL;
 	}
 
-	opd->dir_fd = -1;
-	opd->ret_fd = -1;
-	opd->ret_errno = EINPROGRESS;
-	opd->flags = flags;
-	opd->mode = mode;
-	opd->mid = fsp->mid;
-	opd->in_progress = true;
-	opd->sconn = fsp->conn->sconn;
-	opd->initial_allocation_size = fsp->initial_allocation_size;
+	*opd = (struct aio_open_private_data) {
+		.dir_fd = -1,
+		.ret_fd = -1,
+		.ret_errno = EINPROGRESS,
+		.flags = flags,
+		.mode = mode,
+		.mid = fsp->mid,
+		.in_progress = true,
+		.sconn = fsp->conn->sconn,
+		.initial_allocation_size = fsp->initial_allocation_size,
+	};
 
 	/* Copy our current credentials. */
 	opd->ux_tok = copy_unix_token(opd, get_current_utok(fsp->conn));
-- 
2.17.1


From 010c039689082f3e36e2d4dc0fb88c33883b97c5 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 8 Jan 2019 10:34:11 +0100
Subject: [PATCH 63/66] vfs_aio_pthread: store conn instead of sconn in
 aio_open_private_data

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/modules/vfs_aio_pthread.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/source3/modules/vfs_aio_pthread.c b/source3/modules/vfs_aio_pthread.c
index be74e77b4335..44cbb476c6d4 100644
--- a/source3/modules/vfs_aio_pthread.c
+++ b/source3/modules/vfs_aio_pthread.c
@@ -50,7 +50,7 @@ struct aio_open_private_data {
 	bool in_progress;
 	const char *fname;
 	char *dname;
-	struct smbd_server_connection *sconn;
+	connection_struct *conn;
 	const struct security_unix_token *ux_tok;
 	uint64_t initial_allocation_size;
 	/* Returns. */
@@ -111,7 +111,7 @@ static void aio_open_handle_completion(struct tevent_req *subreq)
 	 * to find the correct connection for a fsp.
 	 * For now we only have one connection, so this is correct...
 	 */
-	xconn = opd->sconn->client->connections;
+	xconn = opd->conn->sconn->client->connections;
 
 	/* Find outstanding event and reschedule. */
 	if (!schedule_deferred_open_message_smb(xconn, opd->mid)) {
@@ -217,7 +217,7 @@ static struct aio_open_private_data *create_private_open_data(const files_struct
 		.mode = mode,
 		.mid = fsp->mid,
 		.in_progress = true,
-		.sconn = fsp->conn->sconn,
+		.conn = fsp->conn,
 		.initial_allocation_size = fsp->initial_allocation_size,
 	};
 
-- 
2.17.1


From 31934161b2969c42467644cf9987360526f6db9b Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Tue, 8 Jan 2019 10:39:56 +0100
Subject: [PATCH 64/66] vfs_aio_pthread: add sync fallback

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/modules/vfs_aio_pthread.c | 32 ++++++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/source3/modules/vfs_aio_pthread.c b/source3/modules/vfs_aio_pthread.c
index 44cbb476c6d4..577180b6b01e 100644
--- a/source3/modules/vfs_aio_pthread.c
+++ b/source3/modules/vfs_aio_pthread.c
@@ -61,6 +61,8 @@ struct aio_open_private_data {
 /* List of outstanding requests we have. */
 static struct aio_open_private_data *open_pd_list;
 
+static void aio_open_do(struct aio_open_private_data *opd);
+
 /************************************************************************
  Find the open private data by mid.
 ***********************************************************************/
@@ -93,9 +95,28 @@ static void aio_open_handle_completion(struct tevent_req *subreq)
 	ret = pthreadpool_tevent_job_recv(subreq);
 	TALLOC_FREE(subreq);
 	if (ret != 0) {
-		smb_panic("aio_open_handle_completion");
-		/* notreached. */
-		return;
+		bool ok;
+
+		if (ret != EAGAIN) {
+			smb_panic("aio_open_handle_completion");
+			/* notreached. */
+			return;
+		}
+		/*
+		 * Make sure we run as the user again
+		 */
+		ok = change_to_user(opd->conn, opd->conn->vuid);
+		if (!ok) {
+			smb_panic("Can't change to user");
+			return;
+		}
+		/*
+		 * If we get EAGAIN from pthreadpool_tevent_job_recv() this
+		 * means the lower level pthreadpool failed to create a new
+		 * thread. Fallback to sync processing in that case to allow
+		 * some progress for the client.
+		 */
+		aio_open_do(opd);
 	}
 
 	DEBUG(10,("aio_open_handle_completion: mid %llu "
@@ -150,6 +171,11 @@ static void aio_open_worker(void *private_data)
 		return;
 	}
 
+	aio_open_do(opd);
+}
+
+static void aio_open_do(struct aio_open_private_data *opd)
+{
 	opd->ret_fd = openat(opd->dir_fd,
 			opd->fname,
 			opd->flags,
-- 
2.17.1


From fcd47f3fac3dfda0ea0f7e3c08c76ffa9ddc3de0 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 27 Dec 2018 15:26:15 +0100
Subject: [PATCH 65/66] Revert "smbd: add smbd_server_connection->raw_ev_ctx
 pointer"

This reverts commit 6114f9545fa856717220658e87f2a60f6767b7f4.

See the discussion in

https://lists.samba.org/archive/samba-technical/2018-December/131731.html

for the reasoning behind this revert.

Signed-off-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
Reviewed-by: Stefan Metzmacher <metze at samba.org>
---
 source3/smbd/globals.h | 1 -
 source3/smbd/msdfs.c   | 5 ++---
 source3/smbd/process.c | 1 -
 3 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 689aa0b6ed1e..02f1e58b77bb 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -877,7 +877,6 @@ struct smbd_server_connection {
 	const struct tsocket_address *remote_address;
 	const char *remote_hostname;
 	struct tevent_context *ev_ctx;
-	struct tevent_context *raw_ev_ctx;
 	struct messaging_context *msg_ctx;
 	struct notify_context *notify_ctx;
 	bool using_smb2;
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index af5888c8a24c..19cb301f56b3 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -258,13 +258,12 @@ static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx,
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	sconn->raw_ev_ctx = samba_tevent_context_init(sconn);
-	if (sconn->raw_ev_ctx == NULL) {
+	sconn->ev_ctx = samba_tevent_context_init(sconn);
+	if (sconn->ev_ctx == NULL) {
 		TALLOC_FREE(sconn);
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	sconn->ev_ctx = sconn->raw_ev_ctx;
 	sconn->msg_ctx = msg;
 
 	conn = conn_new(sconn);
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 03aa2254c156..99693ed1315b 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -3924,7 +3924,6 @@ void smbd_process(struct tevent_context *ev_ctx,
 	sconn->client = client;
 
 	sconn->ev_ctx = ev_ctx;
-	sconn->raw_ev_ctx = ev_ctx;
 	sconn->msg_ctx = msg_ctx;
 
 	ret = pthreadpool_tevent_init(sconn, lp_aio_max_threads(),
-- 
2.17.1


From 9a031b25e992e6e1e093be60cbd96b99633b4778 Mon Sep 17 00:00:00 2001
From: Stefan Metzmacher <metze at samba.org>
Date: Tue, 8 Jan 2019 15:25:22 +0100
Subject: [PATCH 66/66] tevent: deprecate tevent_wrapper api again

Samba doesn't use it anymore and we don't want to
invite new users of that api without further discussion.

Signed-off-by: Stefan Metzmacher <metze at samba.org>
Reviewed-by: Ralph Boehme <slow at samba.org>
Reviewed-by: Volker Lendecke <vl at samba.org>
---
 lib/tevent/testsuite.c        |  1 +
 lib/tevent/tevent.h           | 17 ++++++++++++-----
 lib/tevent/tevent_fd.c        |  1 +
 lib/tevent/tevent_immediate.c |  1 +
 lib/tevent/tevent_signal.c    |  1 +
 lib/tevent/tevent_timed.c     |  1 +
 lib/tevent/tevent_wrapper.c   |  1 +
 7 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/lib/tevent/testsuite.c b/lib/tevent/testsuite.c
index 62a8da3c1a16..ee4c2850230c 100644
--- a/lib/tevent/testsuite.c
+++ b/lib/tevent/testsuite.c
@@ -25,6 +25,7 @@
 */
 
 #include "includes.h"
+#define TEVENT_DEPRECATED 1
 #include "tevent.h"
 #include "system/filesys.h"
 #include "system/select.h"
diff --git a/lib/tevent/tevent.h b/lib/tevent/tevent.h
index c1ed85109d9f..2ec7330e249f 100644
--- a/lib/tevent/tevent.h
+++ b/lib/tevent/tevent.h
@@ -2160,6 +2160,7 @@ bool tevent_register_backend(const char *name, const struct tevent_ops *ops);
 
 /* @} */
 
+#ifdef TEVENT_DEPRECATED
 /**
  * @defgroup tevent_wrapper_ops The tevent wrapper operation functions
  * @ingroup tevent
@@ -2271,6 +2272,7 @@ struct tevent_wrapper_ops {
  * @return                    The wrapper event context, NULL on error.
  *
  * @note Available as of tevent 0.9.37
+ * @note Deprecated as of tevent 0.9.38
  */
 struct tevent_context *tevent_context_wrapper_create(struct tevent_context *main_ev,
 						TALLOC_CTX *mem_ctx,
@@ -2284,7 +2286,7 @@ struct tevent_context *_tevent_context_wrapper_create(struct tevent_context *mai
 						void *pstate,
 						size_t psize,
 						const char *type,
-						const char *location);
+						const char *location) _DEPRECATED_;
 #define tevent_context_wrapper_create(main_ev, mem_ctx, ops, state, type) \
 	_tevent_context_wrapper_create(main_ev, mem_ctx, ops, \
 				       state, sizeof(type), #type, __location__)
@@ -2300,8 +2302,9 @@ struct tevent_context *_tevent_context_wrapper_create(struct tevent_context *mai
  * @see tevent_context_wrapper_create()
  *
  * @note Available as of tevent 0.9.37
+ * @note Deprecated as of tevent 0.9.38
  */
-bool tevent_context_is_wrapper(struct tevent_context *ev);
+bool tevent_context_is_wrapper(struct tevent_context *ev) _DEPRECATED_;
 
 #ifdef DOXYGEN
 /**
@@ -2352,11 +2355,12 @@ bool tevent_context_is_wrapper(struct tevent_context *ev);
  * @see tevent_context_pop_use
  *
  * @note Available as of tevent 0.9.37
+ * @note Deprecated as of tevent 0.9.38
  */
 bool tevent_context_push_use(struct tevent_context *ev);
 #else
 bool _tevent_context_push_use(struct tevent_context *ev,
-				const char *location);
+				const char *location) _DEPRECATED_;
 #define tevent_context_push_use(ev) \
 	_tevent_context_push_use(ev, __location__)
 #endif
@@ -2380,11 +2384,12 @@ bool _tevent_context_push_use(struct tevent_context *ev,
  * @see tevent_context_push_use
  *
  * @note Available as of tevent 0.9.37
+ * @note Deprecated as of tevent 0.9.38
  */
 void tevent_context_pop_use(struct tevent_context *ev);
 #else
 void _tevent_context_pop_use(struct tevent_context *ev,
-			       const char *location);
+			       const char *location) _DEPRECATED_;
 #define tevent_context_pop_use(ev) \
 	_tevent_context_pop_use(ev, __location__)
 #endif
@@ -2406,11 +2411,13 @@ void _tevent_context_pop_use(struct tevent_context *ev,
  * @see tevent_context_wrapper_create
  *
  * @note Available as of tevent 0.9.37
+ * @note Deprecated as of tevent 0.9.38
  */
 bool tevent_context_same_loop(struct tevent_context *ev1,
-			      struct tevent_context *ev2);
+			      struct tevent_context *ev2) _DEPRECATED_;
 
 /* @} */
+#endif /* TEVENT_DEPRECATED */
 
 /**
  * @defgroup tevent_compat The tevent compatibility functions
diff --git a/lib/tevent/tevent_fd.c b/lib/tevent/tevent_fd.c
index b92c45f1ddde..a0557fedbecd 100644
--- a/lib/tevent/tevent_fd.c
+++ b/lib/tevent/tevent_fd.c
@@ -24,6 +24,7 @@
 */
 
 #include "replace.h"
+#define TEVENT_DEPRECATED 1
 #include "tevent.h"
 #include "tevent_internal.h"
 #include "tevent_util.h"
diff --git a/lib/tevent/tevent_immediate.c b/lib/tevent/tevent_immediate.c
index ef7d8a566c0a..d7f8dccc3de9 100644
--- a/lib/tevent/tevent_immediate.c
+++ b/lib/tevent/tevent_immediate.c
@@ -24,6 +24,7 @@
 */
 
 #include "replace.h"
+#define TEVENT_DEPRECATED 1
 #include "tevent.h"
 #include "tevent_internal.h"
 #include "tevent_util.h"
diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c
index 5ca0b8d2ab11..7ebb13d6a39c 100644
--- a/lib/tevent/tevent_signal.c
+++ b/lib/tevent/tevent_signal.c
@@ -26,6 +26,7 @@
 #include "replace.h"
 #include "system/filesys.h"
 #include "system/wait.h"
+#define TEVENT_DEPRECATED 1
 #include "tevent.h"
 #include "tevent_internal.h"
 #include "tevent_util.h"
diff --git a/lib/tevent/tevent_timed.c b/lib/tevent/tevent_timed.c
index b521f096c48a..a78d286a1871 100644
--- a/lib/tevent/tevent_timed.c
+++ b/lib/tevent/tevent_timed.c
@@ -26,6 +26,7 @@
 
 #include "replace.h"
 #include "system/time.h"
+#define TEVENT_DEPRECATED 1
 #include "tevent.h"
 #include "tevent_internal.h"
 #include "tevent_util.h"
diff --git a/lib/tevent/tevent_wrapper.c b/lib/tevent/tevent_wrapper.c
index ce07af983588..deeb64ec177a 100644
--- a/lib/tevent/tevent_wrapper.c
+++ b/lib/tevent/tevent_wrapper.c
@@ -25,6 +25,7 @@
 #ifdef HAVE_PTHREAD
 #include "system/threads.h"
 #endif
+#define TEVENT_DEPRECATED 1
 #include "tevent.h"
 #include "tevent_internal.h"
 #include "tevent_util.h"
-- 
2.17.1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20190111/55ae3e27/signature-0001.sig>


More information about the samba-technical mailing list