[PATCH] Enhance time sampling of async IO VFS functions

Ralph Boehme rb at sernet.de
Mon Feb 29 16:26:34 UTC 2016


On Sun, Feb 28, 2016 at 10:45:47AM -0800, Jeremy Allison wrote:
> On Sun, Feb 28, 2016 at 05:45:24PM +0100, Volker Lendecke wrote:
> > On Sun, Feb 28, 2016 at 08:39:19AM -0800, Jeremy Allison wrote:
> > > > Is it theoretically possible to implement this feature without modifying
> > > > tevent, just within asys.c? Apologies for not coming up with a polished
> > > > proposal mself, but I would like to avoid bloat in such a central
> > > > structure if possible.
> > > 
> > > Sure, if we change the param blocks to the smbd VFS aio
> > > calls then we can do it only inside smbd.
> > > 
> > > I think the question Ralph had is more about if you
> > > think this is worthwhile to add as a feature to tevent ?
> > > 
> > > Or did you just answer that question ? :-) :-).
> > 
> > Right now we have one case where someone really needs this feature. We
> > have many cases that don't. So if there's an elegant way to do this
> > without adding 8 bytes to struct tevent_req I'd prefer that.
> 
> I think that answers the question.
> 
> Ralph, I'm sorry - but can you re-do this by creating
> a 'struct aiocb {... stuff...}' struct for the VFS
> calls, so we don't have to keep adding extra params
> if we need something new ?

attached. Please review & push if ok. I know this is cumbersome to
review, so a big thanks in advance! :)

Hopefully I got the error return wrapping right in all places...

-Ralph

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de,mailto:kontakt@sernet.de
-------------- next part --------------
From 96abc158dc881f2d859279d619c0162ae2a7bf8e Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 26 Feb 2016 10:54:01 +0100
Subject: [PATCH 1/8] s3/vfs: wrap async io function args inside struct
 vfs_aio_state

Subsequent commits that are going to track aio request duration in the
aio backends will use this.

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 examples/VFS/skel_opaque.c       | 15 ++++++++-----
 examples/VFS/skel_transparent.c  | 33 +++++++++++++++-------------
 source3/include/vfs.h            | 17 ++++++++++-----
 source3/modules/vfs_aio_fork.c   | 39 +++++++++++++++------------------
 source3/modules/vfs_aio_linux.c  | 19 ++++++++--------
 source3/modules/vfs_commit.c     | 11 +++++-----
 source3/modules/vfs_default.c    | 18 ++++++++-------
 source3/modules/vfs_full_audit.c | 33 +++++++++++++++-------------
 source3/modules/vfs_glusterfs.c  | 23 +++++++++-----------
 source3/modules/vfs_gpfs.c       | 22 ++++++++++---------
 source3/modules/vfs_time_audit.c | 33 +++++++++++++++-------------
 source3/modules/vfs_tsmsm.c      | 22 ++++++++++---------
 source3/smbd/aio.c               | 33 ++++++++++++++--------------
 source3/smbd/smb2_flush.c        |  7 +++---
 source3/smbd/vfs.c               | 47 ++++++++++++++++++++--------------------
 15 files changed, 195 insertions(+), 177 deletions(-)

diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index 8961627..a92be13 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -241,9 +241,10 @@ static struct tevent_req *skel_pread_send(struct vfs_handle_struct *handle,
 	return NULL;
 }
 
-static ssize_t skel_pread_recv(struct tevent_req *req, int *err)
+static ssize_t skel_pread_recv(struct tevent_req *req,
+			       struct vfs_aio_state *vfs_aio_state)
 {
-	*err = ENOSYS;
+	vfs_aio_state->error = ENOSYS;
 	return -1;
 }
 
@@ -271,9 +272,10 @@ static struct tevent_req *skel_pwrite_send(struct vfs_handle_struct *handle,
 	return NULL;
 }
 
-static ssize_t skel_pwrite_recv(struct tevent_req *req, int *err)
+static ssize_t skel_pwrite_recv(struct tevent_req *req,
+				struct vfs_aio_state *vfs_aio_state)
 {
-	*err = ENOSYS;
+	vfs_aio_state->error = ENOSYS;
 	return -1;
 }
 
@@ -321,9 +323,10 @@ static struct tevent_req *skel_fsync_send(struct vfs_handle_struct *handle,
 	return NULL;
 }
 
-static int skel_fsync_recv(struct tevent_req *req, int *err)
+static int skel_fsync_recv(struct tevent_req *req,
+			   struct vfs_aio_state *vfs_aio_state)
 {
-	*err = ENOSYS;
+	vfs_aio_state->error = ENOSYS;
 	return -1;
 }
 
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index ac82432..3febf97 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -241,7 +241,7 @@ static ssize_t skel_pread(vfs_handle_struct *handle, files_struct *fsp,
 
 struct skel_pread_state {
 	ssize_t ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void skel_pread_done(struct tevent_req *subreq);
@@ -275,20 +275,21 @@ static void skel_pread_done(struct tevent_req *subreq)
 	struct skel_pread_state *state =
 	    tevent_req_data(req, struct skel_pread_state);
 
-	state->ret = SMB_VFS_PREAD_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_PREAD_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	tevent_req_done(req);
 }
 
-static ssize_t skel_pread_recv(struct tevent_req *req, int *err)
+static ssize_t skel_pread_recv(struct tevent_req *req,
+			       struct vfs_aio_state *vfs_aio_state)
 {
 	struct skel_pread_state *state =
 	    tevent_req_data(req, struct skel_pread_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
@@ -306,7 +307,7 @@ static ssize_t skel_pwrite(vfs_handle_struct *handle, files_struct *fsp,
 
 struct skel_pwrite_state {
 	ssize_t ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void skel_pwrite_done(struct tevent_req *subreq);
@@ -341,20 +342,21 @@ static void skel_pwrite_done(struct tevent_req *subreq)
 	struct skel_pwrite_state *state =
 	    tevent_req_data(req, struct skel_pwrite_state);
 
-	state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	tevent_req_done(req);
 }
 
-static ssize_t skel_pwrite_recv(struct tevent_req *req, int *err)
+static ssize_t skel_pwrite_recv(struct tevent_req *req,
+				struct vfs_aio_state *vfs_aio_state)
 {
 	struct skel_pwrite_state *state =
 	    tevent_req_data(req, struct skel_pwrite_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
@@ -391,7 +393,7 @@ static int skel_fsync(vfs_handle_struct *handle, files_struct *fsp)
 
 struct skel_fsync_state {
 	int ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void skel_fsync_done(struct tevent_req *subreq);
@@ -423,20 +425,21 @@ static void skel_fsync_done(struct tevent_req *subreq)
 	struct skel_fsync_state *state =
 	    tevent_req_data(req, struct skel_fsync_state);
 
-	state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	tevent_req_done(req);
 }
 
-static int skel_fsync_recv(struct tevent_req *req, int *err)
+static int skel_fsync_recv(struct tevent_req *req,
+			   struct vfs_aio_state *vfs_aio_state)
 {
 	struct skel_fsync_state *state =
 	    tevent_req_data(req, struct skel_fsync_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index b291206..ab67aab 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -177,6 +177,7 @@
 		const struct smb_filename * */
 /* Version 35 - Change rmdir from const char *, to
 		const struct smb_filename * */
+/* Version 35 - Wrap aio async funtions args in a struct vfs_aio_state */
 
 #define SMB_VFS_INTERFACE_VERSION 35
 
@@ -518,6 +519,10 @@ enum vfs_fallocate_flags {
 	VFS_FALLOCATE_FL_PUNCH_HOLE		= 0x0002,
 };
 
+struct vfs_aio_state {
+	int error;
+};
+
 /*
     Available VFS operations. These values must be in sync with vfs_ops struct
     (struct vfs_fn_pointers and struct vfs_handle_pointers inside of struct vfs_ops).
@@ -599,7 +604,7 @@ struct vfs_fn_pointers {
 					    struct files_struct *fsp,
 					    void *data,
 					    size_t n, off_t offset);
-	ssize_t (*pread_recv_fn)(struct tevent_req *req, int *err);
+	ssize_t (*pread_recv_fn)(struct tevent_req *req, struct vfs_aio_state *state);
 	ssize_t (*write_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, const void *data, size_t n);
 	ssize_t (*pwrite_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, const void *data, size_t n, off_t offset);
 	struct tevent_req *(*pwrite_send_fn)(struct vfs_handle_struct *handle,
@@ -608,7 +613,7 @@ struct vfs_fn_pointers {
 					     struct files_struct *fsp,
 					     const void *data,
 					     size_t n, off_t offset);
-	ssize_t (*pwrite_recv_fn)(struct tevent_req *req, int *err);
+	ssize_t (*pwrite_recv_fn)(struct tevent_req *req, struct vfs_aio_state *state);
 	off_t (*lseek_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, off_t offset, int whence);
 	ssize_t (*sendfile_fn)(struct vfs_handle_struct *handle, int tofd, files_struct *fromfsp, const DATA_BLOB *header, off_t offset, size_t count);
 	ssize_t (*recvfile_fn)(struct vfs_handle_struct *handle, int fromfd, files_struct *tofsp, off_t offset, size_t count);
@@ -620,7 +625,7 @@ struct vfs_fn_pointers {
 					    TALLOC_CTX *mem_ctx,
 					    struct tevent_context *ev,
 					    struct files_struct *fsp);
-	int (*fsync_recv_fn)(struct tevent_req *req, int *err);
+	int (*fsync_recv_fn)(struct tevent_req *req, struct vfs_aio_state *state);
 	int (*stat_fn)(struct vfs_handle_struct *handle, struct smb_filename *smb_fname);
 	int (*fstat_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp, SMB_STRUCT_STAT *sbuf);
 	int (*lstat_fn)(struct vfs_handle_struct *handle, struct smb_filename *smb_filename);
@@ -1022,7 +1027,7 @@ struct tevent_req *smb_vfs_call_pread_send(struct vfs_handle_struct *handle,
 					   struct files_struct *fsp,
 					   void *data,
 					   size_t n, off_t offset);
-ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req, int *perrno);
+ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req, struct vfs_aio_state *state);
 
 ssize_t smb_vfs_call_write(struct vfs_handle_struct *handle,
 			   struct files_struct *fsp, const void *data,
@@ -1036,7 +1041,7 @@ struct tevent_req *smb_vfs_call_pwrite_send(struct vfs_handle_struct *handle,
 					    struct files_struct *fsp,
 					    const void *data,
 					    size_t n, off_t offset);
-ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req, int *perrno);
+ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req, struct vfs_aio_state *state);
 
 off_t smb_vfs_call_lseek(struct vfs_handle_struct *handle,
 			     struct files_struct *fsp, off_t offset,
@@ -1057,7 +1062,7 @@ struct tevent_req *smb_vfs_call_fsync_send(struct vfs_handle_struct *handle,
 					   TALLOC_CTX *mem_ctx,
 					   struct tevent_context *ev,
 					   struct files_struct *fsp);
-int SMB_VFS_FSYNC_RECV(struct tevent_req *req, int *perrno);
+int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *state);
 
 int smb_vfs_call_stat(struct vfs_handle_struct *handle,
 		      struct smb_filename *smb_fname);
diff --git a/source3/modules/vfs_aio_fork.c b/source3/modules/vfs_aio_fork.c
index 472ef0c..4322381 100644
--- a/source3/modules/vfs_aio_fork.c
+++ b/source3/modules/vfs_aio_fork.c
@@ -534,7 +534,7 @@ static int get_idle_child(struct vfs_handle_struct *handle,
 struct aio_fork_pread_state {
 	struct aio_child *child;
 	ssize_t ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void aio_fork_pread_done(struct tevent_req *subreq);
@@ -632,28 +632,27 @@ static void aio_fork_pread_done(struct tevent_req *subreq)
 
 	retbuf = (struct rw_ret *)buf;
 	state->ret = retbuf->size;
-	state->err = retbuf->ret_errno;
+	state->vfs_aio_state.error = retbuf->ret_errno;
 	tevent_req_done(req);
 }
 
-static ssize_t aio_fork_pread_recv(struct tevent_req *req, int *err)
+static ssize_t aio_fork_pread_recv(struct tevent_req *req,
+				   struct vfs_aio_state *vfs_aio_state)
 {
 	struct aio_fork_pread_state *state = tevent_req_data(
 		req, struct aio_fork_pread_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	if (state->ret == -1) {
-		*err = state->err;
-	}
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
 struct aio_fork_pwrite_state {
 	struct aio_child *child;
 	ssize_t ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void aio_fork_pwrite_done(struct tevent_req *subreq);
@@ -748,28 +747,27 @@ static void aio_fork_pwrite_done(struct tevent_req *subreq)
 
 	retbuf = (struct rw_ret *)buf;
 	state->ret = retbuf->size;
-	state->err = retbuf->ret_errno;
+	state->vfs_aio_state.error = retbuf->ret_errno;
 	tevent_req_done(req);
 }
 
-static ssize_t aio_fork_pwrite_recv(struct tevent_req *req, int *err)
+static ssize_t aio_fork_pwrite_recv(struct tevent_req *req,
+				    struct vfs_aio_state *vfs_aio_state)
 {
 	struct aio_fork_pwrite_state *state = tevent_req_data(
 		req, struct aio_fork_pwrite_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	if (state->ret == -1) {
-		*err = state->err;
-	}
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
 struct aio_fork_fsync_state {
 	struct aio_child *child;
 	ssize_t ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void aio_fork_fsync_done(struct tevent_req *subreq);
@@ -856,21 +854,20 @@ static void aio_fork_fsync_done(struct tevent_req *subreq)
 
 	retbuf = (struct rw_ret *)buf;
 	state->ret = retbuf->size;
-	state->err = retbuf->ret_errno;
+	state->vfs_aio_state.error = retbuf->ret_errno;
 	tevent_req_done(req);
 }
 
-static int aio_fork_fsync_recv(struct tevent_req *req, int *err)
+static int aio_fork_fsync_recv(struct tevent_req *req,
+			       struct vfs_aio_state *vfs_aio_state)
 {
 	struct aio_fork_fsync_state *state = tevent_req_data(
 		req, struct aio_fork_fsync_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	if (state->ret == -1) {
-		*err = state->err;
-	}
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
diff --git a/source3/modules/vfs_aio_linux.c b/source3/modules/vfs_aio_linux.c
index 4f6230a..b1d33b5 100644
--- a/source3/modules/vfs_aio_linux.c
+++ b/source3/modules/vfs_aio_linux.c
@@ -139,7 +139,7 @@ static bool init_aio_linux(struct vfs_handle_struct *handle)
 struct aio_linux_state {
 	struct iocb event_iocb;
 	ssize_t ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static struct tevent_req *aio_linux_pread_send(
@@ -289,36 +289,35 @@ static void aio_linux_done(struct tevent_context *event_ctx,
 
 		if (finished.res < 0) {
 			state->ret = -1;
-			state->err = -finished.res;
+			state->vfs_aio_state.error = -finished.res;
 		} else {
 			state->ret = finished.res;
-			state->err = 0;
 		}
 		tevent_req_done(req);
 		num_events -= 1;
 	}
 }
 
-static ssize_t aio_linux_recv(struct tevent_req *req, int *err)
+static ssize_t aio_linux_recv(struct tevent_req *req,
+			      struct vfs_aio_state *vfs_aio_state)
 {
 	struct aio_linux_state *state = tevent_req_data(
 		req, struct aio_linux_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	if (state->ret == -1) {
-		*err = state->err;
-	}
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
-static int aio_linux_int_recv(struct tevent_req *req, int *err)
+static int aio_linux_int_recv(struct tevent_req *req,
+			      struct vfs_aio_state *vfs_aio_state)
 {
 	/*
 	 * Use implicit conversion ssize_t->int
 	 */
-	return aio_linux_recv(req, err);
+	return aio_linux_recv(req, vfs_aio_state);
 }
 
 static struct vfs_fn_pointers vfs_aio_linux_fns = {
diff --git a/source3/modules/vfs_commit.c b/source3/modules/vfs_commit.c
index f1e2743..b870eb2 100644
--- a/source3/modules/vfs_commit.c
+++ b/source3/modules/vfs_commit.c
@@ -289,7 +289,7 @@ struct commit_pwrite_state {
 	struct vfs_handle_struct *handle;
 	struct files_struct *fsp;
 	ssize_t ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void commit_pwrite_written(struct tevent_req *subreq);
@@ -328,7 +328,7 @@ static void commit_pwrite_written(struct tevent_req *subreq)
 		req, struct commit_pwrite_state);
 	int commit_ret;
 
-	state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 
 	if (state->ret <= 0) {
@@ -350,15 +350,16 @@ static void commit_pwrite_written(struct tevent_req *subreq)
 	tevent_req_done(req);
 }
 
-static ssize_t commit_pwrite_recv(struct tevent_req *req, int *err)
+static ssize_t commit_pwrite_recv(struct tevent_req *req,
+				  struct vfs_aio_state *vfs_aio_state)
 {
 	struct commit_pwrite_state *state =
 		tevent_req_data(req, struct commit_pwrite_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index b13b517..0fa7a00 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -742,7 +742,7 @@ struct vfswrap_asys_state {
 	struct asys_context *asys_ctx;
 	struct tevent_req *req;
 	ssize_t ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 	SMBPROFILE_BASIC_ASYNC_STATE(profile_basic);
 	SMBPROFILE_BYTES_ASYNC_STATE(profile_bytes);
 };
@@ -889,33 +889,35 @@ static void vfswrap_asys_finished(struct tevent_context *ev,
 		SMBPROFILE_BASIC_ASYNC_END(state->profile_basic);
 		SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
 		state->ret = result->ret;
-		state->err = result->err;
+		state->vfs_aio_state.error = result->err;
 		tevent_req_defer_callback(req, ev);
 		tevent_req_done(req);
 	}
 }
 
-static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req, int *err)
+static ssize_t vfswrap_asys_ssize_t_recv(struct tevent_req *req,
+					 struct vfs_aio_state *vfs_aio_state)
 {
 	struct vfswrap_asys_state *state = tevent_req_data(
 		req, struct vfswrap_asys_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
-static int vfswrap_asys_int_recv(struct tevent_req *req, int *err)
+static int vfswrap_asys_int_recv(struct tevent_req *req,
+				 struct vfs_aio_state *vfs_aio_state)
 {
 	struct vfswrap_asys_state *state = tevent_req_data(
 		req, struct vfswrap_asys_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
diff --git a/source3/modules/vfs_full_audit.c b/source3/modules/vfs_full_audit.c
index 3dd2005..e4f541b 100644
--- a/source3/modules/vfs_full_audit.c
+++ b/source3/modules/vfs_full_audit.c
@@ -1020,7 +1020,7 @@ struct smb_full_audit_pread_state {
 	vfs_handle_struct *handle;
 	files_struct *fsp;
 	ssize_t ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void smb_full_audit_pread_done(struct tevent_req *subreq);
@@ -1063,17 +1063,18 @@ static void smb_full_audit_pread_done(struct tevent_req *subreq)
 	struct smb_full_audit_pread_state *state = tevent_req_data(
 		req, struct smb_full_audit_pread_state);
 
-	state->ret = SMB_VFS_PREAD_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_PREAD_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	tevent_req_done(req);
 }
 
-static ssize_t smb_full_audit_pread_recv(struct tevent_req *req, int *err)
+static ssize_t smb_full_audit_pread_recv(struct tevent_req *req,
+					 struct vfs_aio_state *vfs_aio_state)
 {
 	struct smb_full_audit_pread_state *state = tevent_req_data(
 		req, struct smb_full_audit_pread_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		do_log(SMB_VFS_OP_PREAD_RECV, false, state->handle, "%s",
 		       fsp_str_do_log(state->fsp));
 		return -1;
@@ -1082,7 +1083,7 @@ static ssize_t smb_full_audit_pread_recv(struct tevent_req *req, int *err)
 	do_log(SMB_VFS_OP_PREAD_RECV, (state->ret >= 0), state->handle, "%s",
 	       fsp_str_do_log(state->fsp));
 
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
@@ -1117,7 +1118,7 @@ struct smb_full_audit_pwrite_state {
 	vfs_handle_struct *handle;
 	files_struct *fsp;
 	ssize_t ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void smb_full_audit_pwrite_done(struct tevent_req *subreq);
@@ -1161,17 +1162,18 @@ static void smb_full_audit_pwrite_done(struct tevent_req *subreq)
 	struct smb_full_audit_pwrite_state *state = tevent_req_data(
 		req, struct smb_full_audit_pwrite_state);
 
-	state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	tevent_req_done(req);
 }
 
-static ssize_t smb_full_audit_pwrite_recv(struct tevent_req *req, int *err)
+static ssize_t smb_full_audit_pwrite_recv(struct tevent_req *req,
+					  struct vfs_aio_state *vfs_aio_state)
 {
 	struct smb_full_audit_pwrite_state *state = tevent_req_data(
 		req, struct smb_full_audit_pwrite_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		do_log(SMB_VFS_OP_PWRITE_RECV, false, state->handle, "%s",
 		       fsp_str_do_log(state->fsp));
 		return -1;
@@ -1180,7 +1182,7 @@ static ssize_t smb_full_audit_pwrite_recv(struct tevent_req *req, int *err)
 	do_log(SMB_VFS_OP_PWRITE_RECV, (state->ret >= 0), state->handle, "%s",
 	       fsp_str_do_log(state->fsp));
 
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
@@ -1258,7 +1260,7 @@ struct smb_full_audit_fsync_state {
 	vfs_handle_struct *handle;
 	files_struct *fsp;
 	int ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void smb_full_audit_fsync_done(struct tevent_req *subreq);
@@ -1299,17 +1301,18 @@ static void smb_full_audit_fsync_done(struct tevent_req *subreq)
 	struct smb_full_audit_fsync_state *state = tevent_req_data(
 		req, struct smb_full_audit_fsync_state);
 
-	state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	tevent_req_done(req);
 }
 
-static int smb_full_audit_fsync_recv(struct tevent_req *req, int *err)
+static int smb_full_audit_fsync_recv(struct tevent_req *req,
+				     struct vfs_aio_state *vfs_aio_state)
 {
 	struct smb_full_audit_fsync_state *state = tevent_req_data(
 		req, struct smb_full_audit_fsync_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		do_log(SMB_VFS_OP_FSYNC_RECV, false, state->handle, "%s",
 		       fsp_str_do_log(state->fsp));
 		return -1;
@@ -1318,7 +1321,7 @@ static int smb_full_audit_fsync_recv(struct tevent_req *req, int *err)
 	do_log(SMB_VFS_OP_FSYNC_RECV, (state->ret >= 0), state->handle, "%s",
 	       fsp_str_do_log(state->fsp));
 
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
index 8e5316d..556c137 100644
--- a/source3/modules/vfs_glusterfs.c
+++ b/source3/modules/vfs_glusterfs.c
@@ -498,9 +498,9 @@ struct glusterfs_aio_wrapper {
 
 struct glusterfs_aio_state {
 	ssize_t ret;
-	int err;
 	struct tevent_req *req;
 	bool cancelled;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static int aio_wrapper_destructor(struct glusterfs_aio_wrapper *wrap)
@@ -524,10 +524,9 @@ static void aio_glusterfs_done(glfs_fd_t *fd, ssize_t ret, void *data)
 
 	if (ret < 0) {
 		state->ret = -1;
-		state->err = errno;
+		state->vfs_aio_state.error = errno;
 	} else {
 		state->ret = ret;
-		state->err = 0;
 	}
 
 	/*
@@ -648,7 +647,7 @@ static struct glusterfs_aio_state *aio_state_create(TALLOC_CTX *mem_ctx)
 		return NULL;
 	}
 
-	state = talloc(NULL, struct glusterfs_aio_state);
+	state = talloc_zero(NULL, struct glusterfs_aio_state);
 
 	if (state == NULL) {
 		TALLOC_FREE(req);
@@ -657,8 +656,6 @@ static struct glusterfs_aio_state *aio_state_create(TALLOC_CTX *mem_ctx)
 
 	talloc_set_destructor(wrapper, aio_wrapper_destructor);
 	state->cancelled = false;
-	state->ret = 0;
-	state->err = 0;
 	state->req = req;
 
 	wrapper->state = state;
@@ -736,7 +733,8 @@ static struct tevent_req *vfs_gluster_pwrite_send(struct vfs_handle_struct
 	return req;
 }
 
-static ssize_t vfs_gluster_recv(struct tevent_req *req, int *err)
+static ssize_t vfs_gluster_recv(struct tevent_req *req,
+				struct vfs_aio_state *vfs_aio_state)
 {
 	struct glusterfs_aio_state *state = NULL;
 	struct glusterfs_aio_wrapper *wrapper = NULL;
@@ -754,13 +752,11 @@ static ssize_t vfs_gluster_recv(struct tevent_req *req, int *err)
 		return -1;
 	}
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	if (state->ret == -1) {
-		*err = state->err;
-	}
 
+	*vfs_aio_state = state->vfs_aio_state;
 	ret = state->ret;
 
 	/* Clean up the state, it is in a NULL context. */
@@ -850,12 +846,13 @@ static struct tevent_req *vfs_gluster_fsync_send(struct vfs_handle_struct
 	return req;
 }
 
-static int vfs_gluster_fsync_recv(struct tevent_req *req, int *err)
+static int vfs_gluster_fsync_recv(struct tevent_req *req,
+				  struct vfs_aio_state *vfs_aio_state)
 {
 	/*
 	 * Use implicit conversion ssize_t->int
 	 */
-	return vfs_gluster_recv(req, err);
+	return vfs_gluster_recv(req, vfs_aio_state);
 }
 
 static int vfs_gluster_stat(struct vfs_handle_struct *handle,
diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c
index 33a30d0..1616b4e 100644
--- a/source3/modules/vfs_gpfs.c
+++ b/source3/modules/vfs_gpfs.c
@@ -2317,8 +2317,8 @@ static ssize_t vfs_gpfs_pread(vfs_handle_struct *handle, files_struct *fsp,
 struct vfs_gpfs_pread_state {
 	struct files_struct *fsp;
 	ssize_t ret;
-	int err;
 	bool was_offline;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void vfs_gpfs_pread_done(struct tevent_req *subreq);
@@ -2355,21 +2355,22 @@ static void vfs_gpfs_pread_done(struct tevent_req *subreq)
 	struct vfs_gpfs_pread_state *state = tevent_req_data(
 		req, struct vfs_gpfs_pread_state);
 
-	state->ret = SMB_VFS_PREAD_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_PREAD_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	tevent_req_done(req);
 }
 
-static ssize_t vfs_gpfs_pread_recv(struct tevent_req *req, int *err)
+static ssize_t vfs_gpfs_pread_recv(struct tevent_req *req,
+				   struct vfs_aio_state *vfs_aio_state)
 {
 	struct vfs_gpfs_pread_state *state = tevent_req_data(
 		req, struct vfs_gpfs_pread_state);
 	struct files_struct *fsp = state->fsp;
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 
 	if ((state->ret != -1) && state->was_offline) {
 		DEBUG(10, ("sending notify\n"));
@@ -2403,8 +2404,8 @@ static ssize_t vfs_gpfs_pwrite(vfs_handle_struct *handle, files_struct *fsp,
 struct vfs_gpfs_pwrite_state {
 	struct files_struct *fsp;
 	ssize_t ret;
-	int err;
 	bool was_offline;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void vfs_gpfs_pwrite_done(struct tevent_req *subreq);
@@ -2442,21 +2443,22 @@ static void vfs_gpfs_pwrite_done(struct tevent_req *subreq)
 	struct vfs_gpfs_pwrite_state *state = tevent_req_data(
 		req, struct vfs_gpfs_pwrite_state);
 
-	state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	tevent_req_done(req);
 }
 
-static ssize_t vfs_gpfs_pwrite_recv(struct tevent_req *req, int *err)
+static ssize_t vfs_gpfs_pwrite_recv(struct tevent_req *req,
+				    struct vfs_aio_state *vfs_aio_state)
 {
 	struct vfs_gpfs_pwrite_state *state = tevent_req_data(
 		req, struct vfs_gpfs_pwrite_state);
 	struct files_struct *fsp = state->fsp;
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 
 	if ((state->ret != -1) && state->was_offline) {
 		DEBUG(10, ("sending notify\n"));
diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c
index 11866fa..08acc4c 100644
--- a/source3/modules/vfs_time_audit.c
+++ b/source3/modules/vfs_time_audit.c
@@ -678,7 +678,7 @@ struct smb_time_audit_pread_state {
 	struct files_struct *fsp;
 	struct timespec ts1;
 	ssize_t ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void smb_time_audit_pread_done(struct tevent_req *subreq);
@@ -715,12 +715,13 @@ static void smb_time_audit_pread_done(struct tevent_req *subreq)
 	struct smb_time_audit_pread_state *state = tevent_req_data(
 		req, struct smb_time_audit_pread_state);
 
-	state->ret = SMB_VFS_PREAD_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_PREAD_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	tevent_req_done(req);
 }
 
-static ssize_t smb_time_audit_pread_recv(struct tevent_req *req, int *err)
+static ssize_t smb_time_audit_pread_recv(struct tevent_req *req,
+					 struct vfs_aio_state *vfs_aio_state)
 {
 	struct smb_time_audit_pread_state *state = tevent_req_data(
 		req, struct smb_time_audit_pread_state);
@@ -734,10 +735,10 @@ static ssize_t smb_time_audit_pread_recv(struct tevent_req *req, int *err)
 		smb_time_audit_log_fsp("pread", timediff, state->fsp);
 	}
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
@@ -786,7 +787,7 @@ struct smb_time_audit_pwrite_state {
 	struct files_struct *fsp;
 	struct timespec ts1;
 	ssize_t ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void smb_time_audit_pwrite_done(struct tevent_req *subreq);
@@ -823,12 +824,13 @@ static void smb_time_audit_pwrite_done(struct tevent_req *subreq)
 	struct smb_time_audit_pwrite_state *state = tevent_req_data(
 		req, struct smb_time_audit_pwrite_state);
 
-	state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	tevent_req_done(req);
 }
 
-static ssize_t smb_time_audit_pwrite_recv(struct tevent_req *req, int *err)
+static ssize_t smb_time_audit_pwrite_recv(struct tevent_req *req,
+					  struct vfs_aio_state *vfs_aio_state)
 {
 	struct smb_time_audit_pwrite_state *state = tevent_req_data(
 		req, struct smb_time_audit_pwrite_state);
@@ -842,10 +844,10 @@ static ssize_t smb_time_audit_pwrite_recv(struct tevent_req *req, int *err)
 		smb_time_audit_log_fsp("pwrite", timediff, state->fsp);
 	}
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
@@ -953,7 +955,7 @@ struct smb_time_audit_fsync_state {
 	struct files_struct *fsp;
 	struct timespec ts1;
 	int ret;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void smb_time_audit_fsync_done(struct tevent_req *subreq);
@@ -988,12 +990,13 @@ static void smb_time_audit_fsync_done(struct tevent_req *subreq)
 	struct smb_time_audit_fsync_state *state = tevent_req_data(
 		req, struct smb_time_audit_fsync_state);
 
-	state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	tevent_req_done(req);
 }
 
-static int smb_time_audit_fsync_recv(struct tevent_req *req, int *err)
+static int smb_time_audit_fsync_recv(struct tevent_req *req,
+				     struct vfs_aio_state *vfs_aio_state)
 {
 	struct smb_time_audit_fsync_state *state = tevent_req_data(
 		req, struct smb_time_audit_fsync_state);
@@ -1007,10 +1010,10 @@ static int smb_time_audit_fsync_recv(struct tevent_req *req, int *err)
 		smb_time_audit_log_fsp("fsync", timediff, state->fsp);
 	}
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
diff --git a/source3/modules/vfs_tsmsm.c b/source3/modules/vfs_tsmsm.c
index e4bc7eb..91daa6f 100644
--- a/source3/modules/vfs_tsmsm.c
+++ b/source3/modules/vfs_tsmsm.c
@@ -289,8 +289,8 @@ static bool tsmsm_aio_force(struct vfs_handle_struct *handle, struct files_struc
 struct tsmsm_pread_state {
 	struct files_struct *fsp;
 	ssize_t ret;
-	int err;
 	bool was_offline;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void tsmsm_pread_done(struct tevent_req *subreq);
@@ -326,17 +326,18 @@ static void tsmsm_pread_done(struct tevent_req *subreq)
 	struct tsmsm_pread_state *state = tevent_req_data(
 		req, struct tsmsm_pread_state);
 
-	state->ret = SMB_VFS_PREAD_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_PREAD_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	tevent_req_done(req);
 }
 
-static ssize_t tsmsm_pread_recv(struct tevent_req *req, int *err)
+static ssize_t tsmsm_pread_recv(struct tevent_req *req,
+				struct vfs_aio_state *vfs_aio_state)
 {
 	struct tsmsm_pread_state *state = tevent_req_data(
 		req, struct tsmsm_pread_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
 	if (state->ret >= 0 && state->was_offline) {
@@ -345,15 +346,15 @@ static ssize_t tsmsm_pread_recv(struct tevent_req *req, int *err)
 			     FILE_NOTIFY_CHANGE_ATTRIBUTES,
 			     fsp->fsp_name->base_name);
 	}
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
 struct tsmsm_pwrite_state {
 	struct files_struct *fsp;
 	ssize_t ret;
-	int err;
 	bool was_offline;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void tsmsm_pwrite_done(struct tevent_req *subreq);
@@ -390,17 +391,18 @@ static void tsmsm_pwrite_done(struct tevent_req *subreq)
 	struct tsmsm_pwrite_state *state = tevent_req_data(
 		req, struct tsmsm_pwrite_state);
 
-	state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->err);
+	state->ret = SMB_VFS_PWRITE_RECV(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	tevent_req_done(req);
 }
 
-static ssize_t tsmsm_pwrite_recv(struct tevent_req *req, int *err)
+static ssize_t tsmsm_pwrite_recv(struct tevent_req *req,
+				 struct vfs_aio_state *vfs_aio_state)
 {
 	struct tsmsm_pwrite_state *state = tevent_req_data(
 		req, struct tsmsm_pwrite_state);
 
-	if (tevent_req_is_unix_error(req, err)) {
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
 	if (state->ret >= 0 && state->was_offline) {
@@ -409,7 +411,7 @@ static ssize_t tsmsm_pwrite_recv(struct tevent_req *req, int *err)
 			     FILE_NOTIFY_CHANGE_ATTRIBUTES,
 			     fsp->fsp_name->base_name);
 	}
-	*err = state->err;
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->ret;
 }
 
diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c
index 32a1ce0..2958ac3 100644
--- a/source3/smbd/aio.c
+++ b/source3/smbd/aio.c
@@ -274,13 +274,13 @@ static void aio_pread_smb1_done(struct tevent_req *req)
 	char *outbuf = (char *)aio_ex->outbuf.data;
 	char *data = smb_buf(outbuf) + 1 /* padding byte */;
 	ssize_t nread;
-	int err;
+	struct vfs_aio_state vfs_aio_state;
 
-	nread = SMB_VFS_PREAD_RECV(req, &err);
+	nread = SMB_VFS_PREAD_RECV(req, &vfs_aio_state);
 	TALLOC_FREE(req);
 
 	DEBUG(10, ("pread_recv returned %d, err = %s\n", (int)nread,
-		   (nread == -1) ? strerror(err) : "no error"));
+		   (nread == -1) ? strerror(vfs_aio_state.error) : "no error"));
 
 	if (fsp == NULL) {
 		DEBUG( 3, ("aio_pread_smb1_done: file closed whilst "
@@ -296,9 +296,9 @@ static void aio_pread_smb1_done(struct tevent_req *req)
 	if (nread < 0) {
 		DEBUG( 3, ("handle_aio_read_complete: file %s nread == %d. "
 			   "Error = %s\n", fsp_str_dbg(fsp), (int)nread,
-			   strerror(err)));
+			   strerror(vfs_aio_state.error)));
 
-		ERROR_NT(map_nt_error_from_unix(err));
+		ERROR_NT(map_nt_error_from_unix(vfs_aio_state.error));
 		outsize = srv_set_message(outbuf,0,0,true);
 	} else {
 		outsize = srv_set_message(outbuf, 12,
@@ -377,13 +377,13 @@ static void pwrite_fsync_write_done(struct tevent_req *subreq)
 	struct pwrite_fsync_state *state = tevent_req_data(
 		req, struct pwrite_fsync_state);
 	connection_struct *conn = state->fsp->conn;
-	int err;
 	bool do_sync;
+	struct vfs_aio_state vfs_aio_state;
 
-	state->nwritten = SMB_VFS_PWRITE_RECV(subreq, &err);
+	state->nwritten = SMB_VFS_PWRITE_RECV(subreq, &vfs_aio_state);
 	TALLOC_FREE(subreq);
 	if (state->nwritten == -1) {
-		tevent_req_error(req, err);
+		tevent_req_error(req, vfs_aio_state.error);
 		return;
 	}
 
@@ -405,12 +405,13 @@ static void pwrite_fsync_sync_done(struct tevent_req *subreq)
 {
 	struct tevent_req *req = tevent_req_callback_data(
 		subreq, struct tevent_req);
-	int ret, err;
+	int ret;
+	struct vfs_aio_state vfs_aio_state;
 
-	ret = SMB_VFS_FSYNC_RECV(subreq, &err);
+	ret = SMB_VFS_FSYNC_RECV(subreq, &vfs_aio_state);
 	TALLOC_FREE(subreq);
 	if (ret == -1) {
-		tevent_req_error(req, err);
+		tevent_req_error(req, vfs_aio_state.error);
 		return;
 	}
 	tevent_req_done(req);
@@ -775,13 +776,13 @@ static void aio_pread_smb2_done(struct tevent_req *req)
 	files_struct *fsp = aio_ex->fsp;
 	NTSTATUS status;
 	ssize_t nread;
-	int err = 0;
+	struct vfs_aio_state vfs_aio_state = { 0 };
 
-	nread = SMB_VFS_PREAD_RECV(req, &err);
+	nread = SMB_VFS_PREAD_RECV(req, &vfs_aio_state);
 	TALLOC_FREE(req);
 
 	DEBUG(10, ("pread_recv returned %d, err = %s\n", (int)nread,
-		   (nread == -1) ? strerror(err) : "no error"));
+		   (nread == -1) ? strerror(vfs_aio_state.error) : "no error"));
 
 	if (fsp == NULL) {
 		DEBUG(3, ("%s: request cancelled (mid[%ju])\n",
@@ -797,7 +798,7 @@ static void aio_pread_smb2_done(struct tevent_req *req)
 	/* Common error or success code processing for async or sync
 	   read returns. */
 
-	status = smb2_read_complete(subreq, nread, err);
+	status = smb2_read_complete(subreq, nread, vfs_aio_state.error);
 
 	if (nread > 0) {
 		fsp->fh->pos = aio_ex->offset + nread;
@@ -810,7 +811,7 @@ static void aio_pread_smb2_done(struct tevent_req *req)
 		   fsp_str_dbg(aio_ex->fsp),
 		   (double)aio_ex->offset,
 		   (unsigned int)nread,
-		   err, nt_errstr(status)));
+		   vfs_aio_state.error, nt_errstr(status)));
 
 	if (!NT_STATUS_IS_OK(status)) {
 		tevent_req_nterror(subreq, status);
diff --git a/source3/smbd/smb2_flush.c b/source3/smbd/smb2_flush.c
index 00b0535..d077c62 100644
--- a/source3/smbd/smb2_flush.c
+++ b/source3/smbd/smb2_flush.c
@@ -190,14 +190,15 @@ static void smbd_smb2_flush_done(struct tevent_req *subreq)
 {
 	struct tevent_req *req = tevent_req_callback_data(
 		subreq, struct tevent_req);
-	int ret, err;
+	int ret;
+	struct vfs_aio_state vfs_aio_state;
 
 	decrement_outstanding_aio_calls();
 
-	ret = SMB_VFS_FSYNC_RECV(subreq, &err);
+	ret = SMB_VFS_FSYNC_RECV(subreq, &vfs_aio_state);
 	TALLOC_FREE(subreq);
 	if (ret == -1) {
-		tevent_req_error(req, err);
+		tevent_req_error(req, vfs_aio_state.error);
 		return;
 	}
 	tevent_req_done(req);
diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index dfc22be..5a385ea 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -1586,8 +1586,9 @@ ssize_t smb_vfs_call_pread(struct vfs_handle_struct *handle,
 }
 
 struct smb_vfs_call_pread_state {
-	ssize_t (*recv_fn)(struct tevent_req *req, int *err);
+	ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
 	ssize_t retval;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void smb_vfs_call_pread_done(struct tevent_req *subreq);
@@ -1625,27 +1626,26 @@ static void smb_vfs_call_pread_done(struct tevent_req *subreq)
 		subreq, struct tevent_req);
 	struct smb_vfs_call_pread_state *state = tevent_req_data(
 		req, struct smb_vfs_call_pread_state);
-	int err;
 
-	state->retval = state->recv_fn(subreq, &err);
+	state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	if (state->retval == -1) {
-		tevent_req_error(req, err);
+		tevent_req_error(req, state->vfs_aio_state.error);
 		return;
 	}
 	tevent_req_done(req);
 }
 
-ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req, int *perrno)
+ssize_t SMB_VFS_PREAD_RECV(struct tevent_req *req,
+			   struct vfs_aio_state *vfs_aio_state)
 {
 	struct smb_vfs_call_pread_state *state = tevent_req_data(
 		req, struct smb_vfs_call_pread_state);
-	int err;
 
-	if (tevent_req_is_unix_error(req, &err)) {
-		*perrno = err;
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->retval;
 }
 
@@ -1666,8 +1666,9 @@ ssize_t smb_vfs_call_pwrite(struct vfs_handle_struct *handle,
 }
 
 struct smb_vfs_call_pwrite_state {
-	ssize_t (*recv_fn)(struct tevent_req *req, int *err);
+	ssize_t (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
 	ssize_t retval;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void smb_vfs_call_pwrite_done(struct tevent_req *subreq);
@@ -1705,27 +1706,26 @@ static void smb_vfs_call_pwrite_done(struct tevent_req *subreq)
 		subreq, struct tevent_req);
 	struct smb_vfs_call_pwrite_state *state = tevent_req_data(
 		req, struct smb_vfs_call_pwrite_state);
-	int err;
 
-	state->retval = state->recv_fn(subreq, &err);
+	state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	if (state->retval == -1) {
-		tevent_req_error(req, err);
+		tevent_req_error(req, state->vfs_aio_state.error);
 		return;
 	}
 	tevent_req_done(req);
 }
 
-ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req, int *perrno)
+ssize_t SMB_VFS_PWRITE_RECV(struct tevent_req *req,
+			    struct vfs_aio_state *vfs_aio_state)
 {
 	struct smb_vfs_call_pwrite_state *state = tevent_req_data(
 		req, struct smb_vfs_call_pwrite_state);
-	int err;
 
-	if (tevent_req_is_unix_error(req, &err)) {
-		*perrno = err;
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->retval;
 }
 
@@ -1770,8 +1770,9 @@ int smb_vfs_call_fsync(struct vfs_handle_struct *handle,
 }
 
 struct smb_vfs_call_fsync_state {
-	int (*recv_fn)(struct tevent_req *req, int *err);
+	int (*recv_fn)(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state);
 	int retval;
+	struct vfs_aio_state vfs_aio_state;
 };
 
 static void smb_vfs_call_fsync_done(struct tevent_req *subreq);
@@ -1806,27 +1807,25 @@ static void smb_vfs_call_fsync_done(struct tevent_req *subreq)
 		subreq, struct tevent_req);
 	struct smb_vfs_call_fsync_state *state = tevent_req_data(
 		req, struct smb_vfs_call_fsync_state);
-	int err;
 
-	state->retval = state->recv_fn(subreq, &err);
+	state->retval = state->recv_fn(subreq, &state->vfs_aio_state);
 	TALLOC_FREE(subreq);
 	if (state->retval == -1) {
-		tevent_req_error(req, err);
+		tevent_req_error(req, state->vfs_aio_state.error);
 		return;
 	}
 	tevent_req_done(req);
 }
 
-int SMB_VFS_FSYNC_RECV(struct tevent_req *req, int *perrno)
+int SMB_VFS_FSYNC_RECV(struct tevent_req *req, struct vfs_aio_state *vfs_aio_state)
 {
 	struct smb_vfs_call_fsync_state *state = tevent_req_data(
 		req, struct smb_vfs_call_fsync_state);
-	int err;
 
-	if (tevent_req_is_unix_error(req, &err)) {
-		*perrno = err;
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
 		return -1;
 	}
+	*vfs_aio_state = state->vfs_aio_state;
 	return state->retval;
 }
 
-- 
2.5.0


From 4c8fbbd892d56ecad253505f3a437d74428d0271 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Mon, 29 Feb 2016 12:17:18 +0100
Subject: [PATCH 2/8] s3/vfs: add duration to vfs_aio_state

This will be used in the aio backends to pass the competion time of the
async request in the backend.

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/include/vfs.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index ab67aab..e3b0f29 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -521,6 +521,7 @@ enum vfs_fallocate_flags {
 
 struct vfs_aio_state {
 	int error;
+	uint64_t duration;
 };
 
 /*
-- 
2.5.0


From dcde9ab2ae9d08e61217b3cea0f6af4d18589091 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 25 Feb 2016 08:06:00 +0100
Subject: [PATCH 3/8] s3:lib/asys: measure async request syscall duration

This uses time functions from lib/util/ which requires pulling in
samba-util. This sucks, but there's just no way of rewrapping a minimal
time utility library without modifying the public samba-util.

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/lib/asys/asys.c        | 13 +++++++++++++
 source3/lib/asys/asys.h        |  1 +
 source3/lib/asys/wscript_build |  2 +-
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/source3/lib/asys/asys.c b/source3/lib/asys/asys.c
index 906d8cf..068b460 100644
--- a/source3/lib/asys/asys.c
+++ b/source3/lib/asys/asys.c
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 #include <errno.h>
 #include "../pthreadpool/pthreadpool.h"
+#include "lib/util/time.h"
 
 struct asys_pwrite_args {
 	int fildes;
@@ -52,6 +53,8 @@ struct asys_job {
 	int err;
 	char busy;
 	char canceled;
+	struct timespec start_time;
+	struct timespec end_time;
 };
 
 struct asys_context {
@@ -189,7 +192,10 @@ static void asys_pwrite_do(void *private_data)
 	struct asys_job *job = (struct asys_job *)private_data;
 	struct asys_pwrite_args *args = &job->args.pwrite_args;
 
+	clock_gettime_mono(&job->start_time);
 	job->ret = pwrite(args->fildes, args->buf, args->nbyte, args->offset);
+	clock_gettime_mono(&job->end_time);
+
 	if (job->ret == -1) {
 		job->err = errno;
 	}
@@ -231,7 +237,10 @@ static void asys_pread_do(void *private_data)
 	struct asys_job *job = (struct asys_job *)private_data;
 	struct asys_pread_args *args = &job->args.pread_args;
 
+	clock_gettime_mono(&job->start_time);
 	job->ret = pread(args->fildes, args->buf, args->nbyte, args->offset);
+	clock_gettime_mono(&job->end_time);
+
 	if (job->ret == -1) {
 		job->err = errno;
 	}
@@ -269,7 +278,10 @@ static void asys_fsync_do(void *private_data)
 	struct asys_job *job = (struct asys_job *)private_data;
 	struct asys_fsync_args *args = &job->args.fsync_args;
 
+	clock_gettime_mono(&job->start_time);
 	job->ret = fsync(args->fildes);
+	clock_gettime_mono(&job->end_time);
+
 	if (job->ret == -1) {
 		job->err = errno;
 	}
@@ -320,6 +332,7 @@ int asys_results(struct asys_context *ctx, struct asys_result *results,
 			result->err = job->err;
 		}
 		result->private_data = job->private_data;
+		result->duration = nsec_time_diff(&job->end_time, &job->start_time);
 
 		job->busy = 0;
 	}
diff --git a/source3/lib/asys/asys.h b/source3/lib/asys/asys.h
index 7c3dfdf..f576bd3 100644
--- a/source3/lib/asys/asys.h
+++ b/source3/lib/asys/asys.h
@@ -108,6 +108,7 @@ struct asys_result {
 	ssize_t ret;
 	int err;
 	void *private_data;
+	uint64_t duration;	/* nanoseconds */
 };
 
 /**
diff --git a/source3/lib/asys/wscript_build b/source3/lib/asys/wscript_build
index 15de977..520994f 100644
--- a/source3/lib/asys/wscript_build
+++ b/source3/lib/asys/wscript_build
@@ -2,7 +2,7 @@
 
 bld.SAMBA3_SUBSYSTEM('LIBASYS',
 		     source='asys.c',
-		     deps='PTHREADPOOL')
+		     deps='PTHREADPOOL samba-util')
 
 bld.SAMBA3_BINARY('asystest',
 		  source='tests.c',
-- 
2.5.0


From 860e184682a3464816867d429dd939366216df45 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 26 Feb 2016 12:29:02 +0100
Subject: [PATCH 4/8] vfs/default: store async VFS op duration we got from
 libasys

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_default.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 0fa7a00..cc905fa 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -890,6 +890,7 @@ static void vfswrap_asys_finished(struct tevent_context *ev,
 		SMBPROFILE_BYTES_ASYNC_END(state->profile_bytes);
 		state->ret = result->ret;
 		state->vfs_aio_state.error = result->err;
+		state->vfs_aio_state.duration = result->duration;
 		tevent_req_defer_callback(req, ev);
 		tevent_req_done(req);
 	}
-- 
2.5.0


From b8bedaba18da2836bd3197a6240f8fcee12f354c Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 26 Feb 2016 09:59:23 +0100
Subject: [PATCH 5/8] vfs/aio_fork: measure async request syscall duration

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_aio_fork.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/source3/modules/vfs_aio_fork.c b/source3/modules/vfs_aio_fork.c
index 4322381..a722102 100644
--- a/source3/modules/vfs_aio_fork.c
+++ b/source3/modules/vfs_aio_fork.c
@@ -128,6 +128,7 @@ struct rw_cmd {
 struct rw_ret {
 	ssize_t size;
 	int ret_errno;
+	uint64_t duration;
 };
 
 struct aio_child_list;
@@ -310,6 +311,7 @@ static void aio_child_loop(int sockfd, struct mmap_area *map)
 		ssize_t ret;
 		struct rw_cmd cmd_struct;
 		struct rw_ret ret_struct;
+		struct timespec start, end;
 
 		ret = read_fd(sockfd, &cmd_struct, sizeof(cmd_struct), &fd);
 		if (ret != sizeof(cmd_struct)) {
@@ -341,6 +343,8 @@ static void aio_child_loop(int sockfd, struct mmap_area *map)
 
 		ZERO_STRUCT(ret_struct);
 
+		clock_gettime_mono(&start);
+
 		switch (cmd_struct.cmd) {
 		case READ_CMD:
 			ret_struct.size = sys_pread(
@@ -366,6 +370,8 @@ static void aio_child_loop(int sockfd, struct mmap_area *map)
 			errno = EINVAL;
 		}
 
+		clock_gettime_mono(&end);
+		ret_struct.duration = nsec_time_diff(&end, &start);
 		DEBUG(10, ("aio_child_loop: syscall returned %d\n",
 			   (int)ret_struct.size));
 
@@ -633,6 +639,7 @@ static void aio_fork_pread_done(struct tevent_req *subreq)
 	retbuf = (struct rw_ret *)buf;
 	state->ret = retbuf->size;
 	state->vfs_aio_state.error = retbuf->ret_errno;
+	state->vfs_aio_state.duration = retbuf->duration;
 	tevent_req_done(req);
 }
 
@@ -748,6 +755,7 @@ static void aio_fork_pwrite_done(struct tevent_req *subreq)
 	retbuf = (struct rw_ret *)buf;
 	state->ret = retbuf->size;
 	state->vfs_aio_state.error = retbuf->ret_errno;
+	state->vfs_aio_state.duration = retbuf->duration;
 	tevent_req_done(req);
 }
 
@@ -855,6 +863,7 @@ static void aio_fork_fsync_done(struct tevent_req *subreq)
 	retbuf = (struct rw_ret *)buf;
 	state->ret = retbuf->size;
 	state->vfs_aio_state.error = retbuf->ret_errno;
+	state->vfs_aio_state.duration = retbuf->duration;
 	tevent_req_done(req);
 }
 
-- 
2.5.0


From 75727f6a2fab23c9e4da5a6337843273d8e46763 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 26 Feb 2016 10:52:39 +0100
Subject: [PATCH 6/8] vfs/aio_linux: measure libaio aio function call duration

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_aio_linux.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/source3/modules/vfs_aio_linux.c b/source3/modules/vfs_aio_linux.c
index b1d33b5..caa3149 100644
--- a/source3/modules/vfs_aio_linux.c
+++ b/source3/modules/vfs_aio_linux.c
@@ -140,6 +140,7 @@ struct aio_linux_state {
 	struct iocb event_iocb;
 	ssize_t ret;
 	struct vfs_aio_state vfs_aio_state;
+	struct timespec start;
 };
 
 static struct tevent_req *aio_linux_pread_send(
@@ -167,6 +168,7 @@ static struct tevent_req *aio_linux_pread_send(
 
 	piocb = &state->event_iocb;
 
+	clock_gettime_mono(&state->start);
 	ret = io_submit(io_ctx, 1, &piocb);
 	if (ret < 0) {
 		tevent_req_error(req, -ret);
@@ -203,6 +205,7 @@ static struct tevent_req *aio_linux_pwrite_send(
 
 	piocb = &state->event_iocb;
 
+	clock_gettime_mono(&state->start);
 	ret = io_submit(io_ctx, 1, &piocb);
 	if (ret < 0) {
 		tevent_req_error(req, -ret);
@@ -237,6 +240,7 @@ static struct tevent_req *aio_linux_fsync_send(
 
 	piocb = &state->event_iocb;
 
+	clock_gettime_mono(&state->start);
 	ret = io_submit(io_ctx, 1, &piocb);
 	if (ret < 0) {
 		tevent_req_error(req, -ret);
@@ -252,10 +256,13 @@ static void aio_linux_done(struct tevent_context *event_ctx,
 			   uint16_t flags, void *private_data)
 {
 	uint64_t num_events = 0;
+	struct timespec end;
 
 	DEBUG(10, ("aio_linux_done called with flags=%d\n",
 		   (int)flags));
 
+	clock_gettime_mono(&end);
+
 	/* Read the number of events available. */
 	if (sys_read(event_fd, &num_events, sizeof(num_events)) !=
 			sizeof(num_events)) {
@@ -293,6 +300,7 @@ static void aio_linux_done(struct tevent_context *event_ctx,
 		} else {
 			state->ret = finished.res;
 		}
+		state->vfs_aio_state.duration = nsec_time_diff(&end, &state->start);
 		tevent_req_done(req);
 		num_events -= 1;
 	}
-- 
2.5.0


From 0f7219dc8a8e7fe967f7d1a73c72a9753db31ca0 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 26 Feb 2016 11:14:36 +0100
Subject: [PATCH 7/8] vfs/glusterfs: measure libglusterfs aio function call
 duration

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_glusterfs.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
index 556c137..4977504 100644
--- a/source3/modules/vfs_glusterfs.c
+++ b/source3/modules/vfs_glusterfs.c
@@ -501,6 +501,7 @@ struct glusterfs_aio_state {
 	struct tevent_req *req;
 	bool cancelled;
 	struct vfs_aio_state vfs_aio_state;
+	struct timespec start;
 };
 
 static int aio_wrapper_destructor(struct glusterfs_aio_wrapper *wrap)
@@ -519,15 +520,19 @@ static void aio_glusterfs_done(glfs_fd_t *fd, ssize_t ret, void *data)
 {
 	struct glusterfs_aio_state *state = NULL;
 	int sts = 0;
+	struct timespec end;
 
 	state = (struct glusterfs_aio_state *)data;
 
+	clock_gettime_mono(&end);
+
 	if (ret < 0) {
 		state->ret = -1;
 		state->vfs_aio_state.error = errno;
 	} else {
 		state->ret = ret;
 	}
+	state->vfs_aio_state.duration = nsec_time_diff(&end, &state->start);
 
 	/*
 	 * Write the state pointer to glusterfs_aio_state to the
@@ -687,6 +692,7 @@ static struct tevent_req *vfs_gluster_pread_send(struct vfs_handle_struct
 		return tevent_req_post(req, ev);
 	}
 
+	clock_gettime_mono(&state->start);
 	ret = glfs_pread_async(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle,
 				fsp), data, n, offset, 0, aio_glusterfs_done,
 				state);
@@ -722,6 +728,7 @@ static struct tevent_req *vfs_gluster_pwrite_send(struct vfs_handle_struct
 		return tevent_req_post(req, ev);
 	}
 
+	clock_gettime_mono(&state->start);
 	ret = glfs_pwrite_async(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle,
 				fsp), data, n, offset, 0, aio_glusterfs_done,
 				state);
@@ -837,6 +844,8 @@ static struct tevent_req *vfs_gluster_fsync_send(struct vfs_handle_struct
 		tevent_req_error(req, EIO);
 		return tevent_req_post(req, ev);
 	}
+
+	clock_gettime_mono(&state->start);
 	ret = glfs_fsync_async(*(glfs_fd_t **)VFS_FETCH_FSP_EXTENSION(handle,
 				fsp), aio_glusterfs_done, req);
 	if (ret < 0) {
-- 
2.5.0


From eb201e9ec82e541d2a4435af5480c84d473dad33 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Fri, 26 Feb 2016 12:54:23 +0100
Subject: [PATCH 8/8] vfs/time_audit: use duration we get from the async
 backend

Finally! The previous commits changed the VFS and the async backend to
pass the duration of an aync operation up the stack.

We now can use this value instead of doing our own sampling which avoids
the following problem:

1. SMB2 read request received, added to the async queue

2. SMB2 create_file request comes in, is processed and blocks for N
   seconds in open()

3. async read completes in the dispatcher thread, completion callback
   will be called when we enter the main tevent loop

4. open() completes after N seconds

5. main tevent event loop is entered, async results are processed

6. async read result is processed, time sampling will include the N
   seconds blocked in open()

Signed-off-by: Ralph Boehme <slow at samba.org>
---
 source3/modules/vfs_time_audit.c | 24 ++++++------------------
 1 file changed, 6 insertions(+), 18 deletions(-)

diff --git a/source3/modules/vfs_time_audit.c b/source3/modules/vfs_time_audit.c
index 08acc4c..915f58e 100644
--- a/source3/modules/vfs_time_audit.c
+++ b/source3/modules/vfs_time_audit.c
@@ -676,7 +676,6 @@ static ssize_t smb_time_audit_pread(vfs_handle_struct *handle,
 
 struct smb_time_audit_pread_state {
 	struct files_struct *fsp;
-	struct timespec ts1;
 	ssize_t ret;
 	struct vfs_aio_state vfs_aio_state;
 };
@@ -696,7 +695,6 @@ static struct tevent_req *smb_time_audit_pread_send(
 	if (req == NULL) {
 		return NULL;
 	}
-	clock_gettime_mono(&state->ts1);
 	state->fsp = fsp;
 
 	subreq = SMB_VFS_NEXT_PREAD_SEND(state, ev, handle, fsp, data,
@@ -725,14 +723,12 @@ static ssize_t smb_time_audit_pread_recv(struct tevent_req *req,
 {
 	struct smb_time_audit_pread_state *state = tevent_req_data(
 		req, struct smb_time_audit_pread_state);
-	struct timespec ts2;
 	double timediff;
 
-	clock_gettime_mono(&ts2);
-	timediff = nsec_time_diff(&ts2,&state->ts1)*1.0e-9;
+	timediff = state->vfs_aio_state.duration * 1.0e-9;
 
 	if (timediff > audit_timeout) {
-		smb_time_audit_log_fsp("pread", timediff, state->fsp);
+		smb_time_audit_log_fsp("async pread", timediff, state->fsp);
 	}
 
 	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
@@ -785,7 +781,6 @@ static ssize_t smb_time_audit_pwrite(vfs_handle_struct *handle,
 
 struct smb_time_audit_pwrite_state {
 	struct files_struct *fsp;
-	struct timespec ts1;
 	ssize_t ret;
 	struct vfs_aio_state vfs_aio_state;
 };
@@ -805,7 +800,6 @@ static struct tevent_req *smb_time_audit_pwrite_send(
 	if (req == NULL) {
 		return NULL;
 	}
-	clock_gettime_mono(&state->ts1);
 	state->fsp = fsp;
 
 	subreq = SMB_VFS_NEXT_PWRITE_SEND(state, ev, handle, fsp, data,
@@ -834,14 +828,12 @@ static ssize_t smb_time_audit_pwrite_recv(struct tevent_req *req,
 {
 	struct smb_time_audit_pwrite_state *state = tevent_req_data(
 		req, struct smb_time_audit_pwrite_state);
-	struct timespec ts2;
 	double timediff;
 
-	clock_gettime_mono(&ts2);
-	timediff = nsec_time_diff(&ts2,&state->ts1)*1.0e-9;
+	timediff = state->vfs_aio_state.duration * 1.0e-9;
 
 	if (timediff > audit_timeout) {
-		smb_time_audit_log_fsp("pwrite", timediff, state->fsp);
+		smb_time_audit_log_fsp("async pwrite", timediff, state->fsp);
 	}
 
 	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
@@ -953,7 +945,6 @@ static int smb_time_audit_fsync(vfs_handle_struct *handle, files_struct *fsp)
 
 struct smb_time_audit_fsync_state {
 	struct files_struct *fsp;
-	struct timespec ts1;
 	int ret;
 	struct vfs_aio_state vfs_aio_state;
 };
@@ -972,7 +963,6 @@ static struct tevent_req *smb_time_audit_fsync_send(
 	if (req == NULL) {
 		return NULL;
 	}
-	clock_gettime_mono(&state->ts1);
 	state->fsp = fsp;
 
 	subreq = SMB_VFS_NEXT_FSYNC_SEND(state, ev, handle, fsp);
@@ -1000,14 +990,12 @@ static int smb_time_audit_fsync_recv(struct tevent_req *req,
 {
 	struct smb_time_audit_fsync_state *state = tevent_req_data(
 		req, struct smb_time_audit_fsync_state);
-	struct timespec ts2;
 	double timediff;
 
-	clock_gettime_mono(&ts2);
-	timediff = nsec_time_diff(&ts2,&state->ts1)*1.0e-9;
+	timediff = state->vfs_aio_state.duration * 1.0e-9;
 
 	if (timediff > audit_timeout) {
-		smb_time_audit_log_fsp("fsync", timediff, state->fsp);
+		smb_time_audit_log_fsp("async fsync", timediff, state->fsp);
 	}
 
 	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
-- 
2.5.0



More information about the samba-technical mailing list