r3336: use a struct ntvfs_async_state to be able to do async chaning of ntvfs modules
authorStefan Metzmacher <metze@samba.org>
Thu, 28 Oct 2004 21:48:53 +0000 (21:48 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:04:57 +0000 (13:04 -0500)
the idea is that a passthru module can use ntvfs_async_state_push() before
calling ntvfs_next_*() and in the _send function it calls
ntvfs_async_state_pop() and then call the upper layer send_fn itself

- ntvfs_nbench is now fully async

- the ntvfs_map_*() functions and the trans(2) mapping functions are not converted yet

metze
(This used to be commit fde64c0dc142b53d128c8ba09af048dc58d8ef3a)

14 files changed:
source4/include/smb.h
source4/ntvfs/cifs/vfs_cifs.c
source4/ntvfs/nbench/vfs_nbench.c
source4/ntvfs/ntvfs.h
source4/ntvfs/ntvfs_base.c
source4/ntvfs/ntvfs_generic.c
source4/ntvfs/ntvfs_util.c
source4/ntvfs/posix/pvfs_lock.c
source4/ntvfs/posix/pvfs_wait.c
source4/smb_server/reply.c
source4/smb_server/request.c
source4/smb_server/search.c
source4/smb_server/smb_server.c
source4/smb_server/smb_server.h

index 4354eae8621665ce914d28160c2a42efc53e8493..ccb245ccdd311ddcf4c69e1e3bb799e96aecfb11 100644 (file)
@@ -575,12 +575,6 @@ typedef struct nt_user_token {
 
 #define DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH 14
 
-
-/* a set of flags to control handling of request structures */
-#define REQ_CONTROL_LARGE     (1<<1) /* allow replies larger than max_xmit */
-#define REQ_CONTROL_ASYNC     (1<<2) /* the backend will answer this one later */
-#define REQ_CONTROL_MAY_ASYNC (1<<3) /* the backend is allowed to answer async */
-
 /* passed to br lock code */
 enum brl_type {READ_LOCK, WRITE_LOCK, PENDING_READ_LOCK, PENDING_WRITE_LOCK};
 
index 1a0f1f2f71e062e7935722e3b2e088636865d78a..9c5cfd95845092d3534a1cfb14043952296a8c9d 100644 (file)
@@ -182,8 +182,8 @@ static void async_simple(struct smbcli_request *c_req)
 {
        struct async_info *async = c_req->async.private;
        struct smbsrv_request *req = async->req;
-       req->async.status = smbcli_request_simple_recv(c_req);
-       req->async.send_fn(req);
+       req->async_states->status = smbcli_request_simple_recv(c_req);
+       req->async_states->send_fn(req);
 }
 
 
@@ -199,7 +199,7 @@ static void async_simple(struct smbcli_request *c_req)
                c_req->async.private = async; \
        } \
        c_req->async.fn = async_fn; \
-       req->control_flags |= REQ_CONTROL_ASYNC; \
+       req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; \
        return NT_STATUS_OK; \
 } while (0)
 
@@ -219,7 +219,7 @@ static NTSTATUS cvfs_unlink(struct ntvfs_module_context *ntvfs,
 
        /* see if the front end will allow us to perform this
           function asynchronously.  */
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_unlink(private->tree, unl);
        }
 
@@ -235,8 +235,8 @@ static void async_ioctl(struct smbcli_request *c_req)
 {
        struct async_info *async = c_req->async.private;
        struct smbsrv_request *req = async->req;
-       req->async.status = smb_raw_ioctl_recv(c_req, req, async->parms);
-       req->async.send_fn(req);
+       req->async_states->status = smb_raw_ioctl_recv(c_req, req, async->parms);
+       req->async_states->send_fn(req);
 }
 
 /*
@@ -252,7 +252,7 @@ static NTSTATUS cvfs_ioctl(struct ntvfs_module_context *ntvfs,
 
        /* see if the front end will allow us to perform this
           function asynchronously.  */
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_ioctl(private->tree, req, io);
        }
 
@@ -272,7 +272,7 @@ static NTSTATUS cvfs_chkpath(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_chkpath(private->tree, cp);
        }
 
@@ -288,8 +288,8 @@ static void async_qpathinfo(struct smbcli_request *c_req)
 {
        struct async_info *async = c_req->async.private;
        struct smbsrv_request *req = async->req;
-       req->async.status = smb_raw_pathinfo_recv(c_req, req, async->parms);
-       req->async.send_fn(req);
+       req->async_states->status = smb_raw_pathinfo_recv(c_req, req, async->parms);
+       req->async_states->send_fn(req);
 }
 
 /*
@@ -303,7 +303,7 @@ static NTSTATUS cvfs_qpathinfo(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_pathinfo(private->tree, req, info);
        }
 
@@ -319,8 +319,8 @@ static void async_qfileinfo(struct smbcli_request *c_req)
 {
        struct async_info *async = c_req->async.private;
        struct smbsrv_request *req = async->req;
-       req->async.status = smb_raw_fileinfo_recv(c_req, req, async->parms);
-       req->async.send_fn(req);
+       req->async_states->status = smb_raw_fileinfo_recv(c_req, req, async->parms);
+       req->async_states->send_fn(req);
 }
 
 /*
@@ -334,7 +334,7 @@ static NTSTATUS cvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_fileinfo(private->tree, req, info);
        }
 
@@ -355,7 +355,7 @@ static NTSTATUS cvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_setpathinfo(private->tree, st);
        }
 
@@ -372,8 +372,8 @@ static void async_open(struct smbcli_request *c_req)
 {
        struct async_info *async = c_req->async.private;
        struct smbsrv_request *req = async->req;
-       req->async.status = smb_raw_open_recv(c_req, req, async->parms);
-       req->async.send_fn(req);
+       req->async_states->status = smb_raw_open_recv(c_req, req, async->parms);
+       req->async_states->send_fn(req);
 }
 
 /*
@@ -392,7 +392,7 @@ static NTSTATUS cvfs_open(struct ntvfs_module_context *ntvfs,
                return ntvfs_map_open(req, io, ntvfs);
        }
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_open(private->tree, req, io);
        }
 
@@ -412,7 +412,7 @@ static NTSTATUS cvfs_mkdir(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_mkdir(private->tree, md);
        }
 
@@ -432,7 +432,7 @@ static NTSTATUS cvfs_rmdir(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_rmdir(private->tree, rd);
        }
        c_req = smb_raw_rmdir_send(private->tree, rd);
@@ -451,7 +451,7 @@ static NTSTATUS cvfs_rename(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_rename(private->tree, ren);
        }
 
@@ -476,8 +476,8 @@ static void async_read(struct smbcli_request *c_req)
 {
        struct async_info *async = c_req->async.private;
        struct smbsrv_request *req = async->req;
-       req->async.status = smb_raw_read_recv(c_req, async->parms);
-       req->async.send_fn(req);
+       req->async_states->status = smb_raw_read_recv(c_req, async->parms);
+       req->async_states->send_fn(req);
 }
 
 /*
@@ -496,7 +496,7 @@ static NTSTATUS cvfs_read(struct ntvfs_module_context *ntvfs,
                return ntvfs_map_read(req, rd, ntvfs);
        }
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_read(private->tree, rd);
        }
 
@@ -512,8 +512,8 @@ static void async_write(struct smbcli_request *c_req)
 {
        struct async_info *async = c_req->async.private;
        struct smbsrv_request *req = async->req;
-       req->async.status = smb_raw_write_recv(c_req, async->parms);
-       req->async.send_fn(req);
+       req->async_states->status = smb_raw_write_recv(c_req, async->parms);
+       req->async_states->send_fn(req);
 }
 
 /*
@@ -532,7 +532,7 @@ static NTSTATUS cvfs_write(struct ntvfs_module_context *ntvfs,
                return ntvfs_map_write(req, wr, ntvfs);
        }
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_write(private->tree, wr);
        }
 
@@ -552,7 +552,7 @@ static NTSTATUS cvfs_seek(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_seek(private->tree, io);
        }
 
@@ -572,7 +572,7 @@ static NTSTATUS cvfs_flush(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_flush(private->tree, io);
        }
 
@@ -597,7 +597,7 @@ static NTSTATUS cvfs_close(struct ntvfs_module_context *ntvfs,
                return ntvfs_map_close(req, io, ntvfs);
        }
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_close(private->tree, io);
        }
 
@@ -617,7 +617,7 @@ static NTSTATUS cvfs_exit(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_exit(private->tree->session);
        }
 
@@ -662,7 +662,7 @@ static NTSTATUS cvfs_lock(struct ntvfs_module_context *ntvfs,
                return ntvfs_map_lock(req, lck, ntvfs);
        }
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_lock(private->tree, lck);
        }
 
@@ -682,7 +682,7 @@ static NTSTATUS cvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_setfileinfo(private->tree, info);
        }
        c_req = smb_raw_setfileinfo_send(private->tree, info);
@@ -698,8 +698,8 @@ static void async_fsinfo(struct smbcli_request *c_req)
 {
        struct async_info *async = c_req->async.private;
        struct smbsrv_request *req = async->req;
-       req->async.status = smb_raw_fsinfo_recv(c_req, req, async->parms);
-       req->async.send_fn(req);
+       req->async_states->status = smb_raw_fsinfo_recv(c_req, req, async->parms);
+       req->async_states->send_fn(req);
 }
 
 /*
@@ -713,7 +713,7 @@ static NTSTATUS cvfs_fsinfo(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_fsinfo(private->tree, req, fs);
        }
 
@@ -777,8 +777,8 @@ static void async_trans2(struct smbcli_request *c_req)
 {
        struct async_info *async = c_req->async.private;
        struct smbsrv_request *req = async->req;
-       req->async.status = smb_raw_trans2_recv(c_req, req, async->parms);
-       req->async.send_fn(req);
+       req->async_states->status = smb_raw_trans2_recv(c_req, req, async->parms);
+       req->async_states->send_fn(req);
 }
 
 /* raw trans2 */
@@ -790,7 +790,7 @@ static NTSTATUS cvfs_trans2(struct ntvfs_module_context *ntvfs,
 
        SETUP_PID;
 
-       if (!(req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                return smb_raw_trans2(private->tree, req, trans2);
        }
 
index 482f0208a2ba7450056328bb5ec6af66954b0927..ab2d7af7b1c5a5d366e46b087653dfd7a835d3e5 100644 (file)
@@ -47,7 +47,7 @@ static void nbench_log(struct nbench_private *private,
        vasprintf(&s, format, ap);
        va_end(ap);
 
-       write(private->log_fd, s, strlen(s));
+       //write(private->log_fd, s, strlen(s));
        free(s);
 }
 
@@ -58,11 +58,39 @@ static void nbench_log(struct nbench_private *private,
   async calls are a pain for the nbench module as it makes pulling the
   status code and any result parameters much harder.
 */
-#define PASS_THRU_REQ(ntvfs, req, op, args) do { \
-       req->control_flags &= ~REQ_CONTROL_MAY_ASYNC; \
+#define PASS_THRU_REQ_PRE_ASYNC(ntvfs, req, op, par1) do { \
+       status = ntvfs_async_state_push(req, par1, nbench_##op##_send, ntvfs); \
+       if (!NT_STATUS_IS_OK(status)) { \
+               return status; \
+       } \
+} while (0)
+
+#define PASS_THRU_REQ_POST_ASYNC(req) do { \
+       req->async_states->status = status; \
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
+DEBUG(0,("NBENCH S 0x%04X: %s: %s 0x%X\n", req->mid, __FUNCTION__, nt_errstr(status),req->async_states->state)); \
+               req->async_states->send_fn(req); \
+       } else { \
+DEBUG(0,("NBENCH A 0x%04X: %s: %s\n", req->mid, __FUNCTION__, nt_errstr(status))); \
+       } \
+} while (0)
+
+#define PASS_THRU_REQ(ntvfs, req, op, par1, args) do { \
+       PASS_THRU_REQ_PRE_ASYNC(ntvfs, req, op, par1); \
        status = ntvfs_next_##op args; \
+       PASS_THRU_REQ_POST_ASYNC(req); \
 } while (0)
 
+#define PASS_THRU_REP_POST(req) do { \
+       ntvfs_async_state_pop(req); \
+       if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) { \
+DEBUG(0,("NBENCH  A0x%04X: %s: %s\n", req->mid, __FUNCTION__, nt_errstr(req->async_states->status))); \
+               req->async_states->send_fn(req); \
+       } \
+} while (0)
+
+#define PASS_THRU_REP_PRE(req) \
+       struct nbench_private *nprivates = req->async_states->ntvfs->private_data
 
 /*
   connect to a share - used when a tree_connect operation comes in.
@@ -70,25 +98,25 @@ static void nbench_log(struct nbench_private *private,
 static NTSTATUS nbench_connect(struct ntvfs_module_context *ntvfs,
                               struct smbsrv_request *req, const char *sharename)
 {
-       struct nbench_private *private;
+       struct nbench_private *nprivates;
        NTSTATUS status;
        char *logname = NULL;
 
-       private = talloc_p(req->tcon, struct nbench_private);
-       if (!private) {
+       nprivates = talloc_p(req->tcon, struct nbench_private);
+       if (!nprivates) {
                return NT_STATUS_NO_MEMORY;
        }
-
+#if 0
        asprintf(&logname, "/tmp/nbenchlog%d.%u", ntvfs->depth, getpid());
-       private->log_fd = sys_open(logname, O_WRONLY|O_CREAT|O_APPEND, 0644);
+       nprivates->log_fd = sys_open(logname, O_WRONLY|O_CREAT|O_APPEND, 0644);
        free(logname);
 
-       if (private->log_fd == -1) {
+       if (nprivates->log_fd == -1) {
                DEBUG(0,("Failed to open nbench log\n"));
                return NT_STATUS_UNSUCCESSFUL;
        }
-
-       ntvfs->private_data = private;
+#endif
+       ntvfs->private_data = nprivates;
 
        status = ntvfs_next_connect(ntvfs, req, sharename);
 
@@ -101,13 +129,13 @@ static NTSTATUS nbench_connect(struct ntvfs_module_context *ntvfs,
 static NTSTATUS nbench_disconnect(struct ntvfs_module_context *ntvfs,
                                  struct smbsrv_tcon *tcon)
 {
-       struct nbench_private *private = ntvfs->private_data;
+       struct nbench_private *nprivates = ntvfs->private_data;
        NTSTATUS status;
 
-       close(private->log_fd);
+       close(nprivates->log_fd);
 
        status = ntvfs_next_disconnect(ntvfs, tcon);
+
        return status;
 }
 
@@ -115,17 +143,24 @@ static NTSTATUS nbench_disconnect(struct ntvfs_module_context *ntvfs,
   delete a file - the dirtype specifies the file types to include in the search. 
   The name can contain CIFS wildcards, but rarely does (except with OS/2 clients)
 */
+static void nbench_unlink_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+       struct smb_unlink *unl = req->async_states->private_data;
+
+       nbench_log(nprivates, "Unlink \"%s\" 0x%x %s\n", 
+                  unl->in.pattern, unl->in.attrib, 
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_unlink(struct ntvfs_module_context *ntvfs,
                              struct smbsrv_request *req, struct smb_unlink *unl)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, unlink, (ntvfs, req, unl));
-
-       nbench_log(private, "Unlink \"%s\" 0x%x %s\n", 
-                  unl->in.pattern, unl->in.attrib, 
-                  get_nt_error_c_code(status));
+       PASS_THRU_REQ(ntvfs, req, unlink, unl, (ntvfs, req, unl));
 
        return status;
 }
@@ -133,15 +168,21 @@ static NTSTATUS nbench_unlink(struct ntvfs_module_context *ntvfs,
 /*
   ioctl interface
 */
+static void nbench_ioctl_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+
+       nbench_log(nprivates, "Ioctl - NOT HANDLED\n");
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_ioctl(struct ntvfs_module_context *ntvfs,
                             struct smbsrv_request *req, union smb_ioctl *io)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, ioctl, (ntvfs, req, io));
-
-       nbench_log(private, "Ioctl - NOT HANDLED\n");
+       PASS_THRU_REQ(ntvfs, req, ioctl, io, (ntvfs, req, io));
 
        return status;
 }
@@ -149,17 +190,24 @@ static NTSTATUS nbench_ioctl(struct ntvfs_module_context *ntvfs,
 /*
   check if a directory exists
 */
+static void nbench_chkpath_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+       struct smb_chkpath *cp = req->async_states->private_data;
+
+       nbench_log(nprivates, "Chkpath \"%s\" %s\n", 
+                  cp->in.path, 
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_chkpath(struct ntvfs_module_context *ntvfs,
                               struct smbsrv_request *req, struct smb_chkpath *cp)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, chkpath, (ntvfs, req, cp));
-
-       nbench_log(private, "Chkpath \"%s\" %s\n", 
-                  cp->in.path, 
-                  get_nt_error_c_code(status));
+       PASS_THRU_REQ(ntvfs, req, chkpath, cp, (ntvfs, req, cp));
 
        return status;
 }
@@ -167,18 +215,25 @@ static NTSTATUS nbench_chkpath(struct ntvfs_module_context *ntvfs,
 /*
   return info on a pathname
 */
+static void nbench_qpathinfo_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+       union smb_fileinfo *info = req->async_states->private_data;
+
+       nbench_log(nprivates, "QUERY_PATH_INFORMATION \"%s\" %d %s\n", 
+                  info->generic.in.fname, 
+                  info->generic.level,
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_qpathinfo(struct ntvfs_module_context *ntvfs,
                                 struct smbsrv_request *req, union smb_fileinfo *info)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, qpathinfo, (ntvfs, req, info));
-
-       nbench_log(private, "QUERY_PATH_INFORMATION \"%s\" %d %s\n", 
-                  info->generic.in.fname, 
-                  info->generic.level,
-                  get_nt_error_c_code(status));
+       PASS_THRU_REQ(ntvfs, req, qpathinfo, info, (ntvfs, req, info));
 
        return status;
 }
@@ -186,38 +241,51 @@ static NTSTATUS nbench_qpathinfo(struct ntvfs_module_context *ntvfs,
 /*
   query info on a open file
 */
+static void nbench_qfileinfo_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+       union smb_fileinfo *info = req->async_states->private_data;
+
+       nbench_log(nprivates, "QUERY_FILE_INFORMATION %d %d %s\n", 
+                  info->generic.in.fnum, 
+                  info->generic.level,
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_qfileinfo(struct ntvfs_module_context *ntvfs,
                                 struct smbsrv_request *req, union smb_fileinfo *info)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, qfileinfo, (ntvfs, req, info));
-
-       nbench_log(private, "QUERY_FILE_INFORMATION %d %d %s\n", 
-                  info->generic.in.fnum, 
-                  info->generic.level,
-                  get_nt_error_c_code(status));
+       PASS_THRU_REQ(ntvfs, req, qfileinfo, info, (ntvfs, req, info));
 
        return status;
 }
 
-
 /*
   set info on a pathname
 */
+static void nbench_setpathinfo_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+       union smb_setfileinfo *st = req->async_states->private_data;
+
+       nbench_log(nprivates, "SET_PATH_INFORMATION \"%s\" %d %s\n", 
+                  st->generic.file.fname, 
+                  st->generic.level,
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_setpathinfo(struct ntvfs_module_context *ntvfs,
                                   struct smbsrv_request *req, union smb_setfileinfo *st)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, setpathinfo, (ntvfs, req, st));
-
-       nbench_log(private, "SET_PATH_INFORMATION \"%s\" %d %s\n", 
-                  st->generic.file.fname, 
-                  st->generic.level,
-                  get_nt_error_c_code(status));
+       PASS_THRU_REQ(ntvfs, req, setpathinfo, st, (ntvfs, req, st));
 
        return status;
 }
@@ -225,47 +293,58 @@ static NTSTATUS nbench_setpathinfo(struct ntvfs_module_context *ntvfs,
 /*
   open a file
 */
-static NTSTATUS nbench_open(struct ntvfs_module_context *ntvfs,
-                           struct smbsrv_request *req, union smb_open *io)
+static void nbench_open_send(struct smbsrv_request *req)
 {
-       struct nbench_private *private = ntvfs->private_data;
-       NTSTATUS status;
-
-       PASS_THRU_REQ(ntvfs, req, open, (ntvfs, req, io));
-
-       DEBUG(0,("%d: %s\n", ntvfs->depth, get_nt_error_c_code(status)));
+       PASS_THRU_REP_PRE(req);
+       union smb_open *io = req->async_states->private_data;
 
        switch (io->generic.level) {
        case RAW_OPEN_NTCREATEX:
-               nbench_log(private, "NTCreateX \"%s\" 0x%x 0x%x %d %s\n", 
+               nbench_log(nprivates, "NTCreateX \"%s\" 0x%x 0x%x %d %s\n", 
                           io->ntcreatex.in.fname, 
                           io->ntcreatex.in.create_options, 
                           io->ntcreatex.in.open_disposition, 
                           io->ntcreatex.out.fnum,
-                          get_nt_error_c_code(status));
+                          get_nt_error_c_code(req->async_states->status));
                break;
 
        default:
-               nbench_log(private, "Open-%d - NOT HANDLED\n",
+               nbench_log(nprivates, "Open-%d - NOT HANDLED\n",
                           io->generic.level);
                break;
        }
 
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_open(struct ntvfs_module_context *ntvfs,
+                           struct smbsrv_request *req, union smb_open *io)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, open, io, (ntvfs, req, io));
+
        return status;
 }
 
 /*
   create a directory
 */
+static void nbench_mkdir_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+
+       nbench_log(nprivates, "Mkdir - NOT HANDLED\n");
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_mkdir(struct ntvfs_module_context *ntvfs,
                             struct smbsrv_request *req, union smb_mkdir *md)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, mkdir, (ntvfs, req, md));
-
-       nbench_log(private, "Mkdir - NOT HANDLED\n");
+       PASS_THRU_REQ(ntvfs, req, mkdir, md, (ntvfs, req, md));
 
        return status;
 }
@@ -273,17 +352,24 @@ static NTSTATUS nbench_mkdir(struct ntvfs_module_context *ntvfs,
 /*
   remove a directory
 */
+static void nbench_rmdir_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+       struct smb_rmdir *rd = req->async_states->private_data;
+
+       nbench_log(nprivates, "Rmdir \"%s\" %s\n", 
+                  rd->in.path, 
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_rmdir(struct ntvfs_module_context *ntvfs,
                             struct smbsrv_request *req, struct smb_rmdir *rd)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, rmdir, (ntvfs, req, rd));
-
-       nbench_log(private, "Rmdir \"%s\" %s\n", 
-                  rd->in.path, 
-                  get_nt_error_c_code(status));
+       PASS_THRU_REQ(ntvfs, req, rmdir, rd, (ntvfs, req, rd));
 
        return status;
 }
@@ -291,43 +377,56 @@ static NTSTATUS nbench_rmdir(struct ntvfs_module_context *ntvfs,
 /*
   rename a set of files
 */
-static NTSTATUS nbench_rename(struct ntvfs_module_context *ntvfs,
-                             struct smbsrv_request *req, union smb_rename *ren)
+static void nbench_rename_send(struct smbsrv_request *req)
 {
-       struct nbench_private *private = ntvfs->private_data;
-       NTSTATUS status;
-
-       PASS_THRU_REQ(ntvfs, req, rename, (ntvfs, req, ren));
+       PASS_THRU_REP_PRE(req);
+       union smb_rename *ren = req->async_states->private_data;
 
        switch (ren->generic.level) {
        case RAW_RENAME_RENAME:
-               nbench_log(private, "Rename \"%s\" \"%s\" %s\n", 
+               nbench_log(nprivates, "Rename \"%s\" \"%s\" %s\n", 
                           ren->rename.in.pattern1, 
                           ren->rename.in.pattern2, 
-                          get_nt_error_c_code(status));
+                          get_nt_error_c_code(req->async_states->status));
                break;
 
        default:
-               nbench_log(private, "Rename-%d - NOT HANDLED\n",
+               nbench_log(nprivates, "Rename-%d - NOT HANDLED\n",
                           ren->generic.level);
                break;
        }
 
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_rename(struct ntvfs_module_context *ntvfs,
+                             struct smbsrv_request *req, union smb_rename *ren)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, rename, ren, (ntvfs, req, ren));
+
        return status;
 }
 
 /*
   copy a set of files
 */
+static void nbench_copy_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+
+       nbench_log(nprivates, "Copy - NOT HANDLED\n");
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_copy(struct ntvfs_module_context *ntvfs,
                            struct smbsrv_request *req, struct smb_copy *cp)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, copy, (ntvfs, req, cp));
-
-       nbench_log(private, "Copy - NOT HANDLED\n");
+       PASS_THRU_REQ(ntvfs, req, copy, cp, (ntvfs, req, cp));
 
        return status;
 }
@@ -335,83 +434,103 @@ static NTSTATUS nbench_copy(struct ntvfs_module_context *ntvfs,
 /*
   read from a file
 */
-static NTSTATUS nbench_read(struct ntvfs_module_context *ntvfs,
-                           struct smbsrv_request *req, union smb_read *rd)
+static void nbench_read_send(struct smbsrv_request *req)
 {
-       struct nbench_private *private = ntvfs->private_data;
-       NTSTATUS status;
-
-       PASS_THRU_REQ(ntvfs, req, read, (ntvfs, req, rd));
+       PASS_THRU_REP_PRE(req);
+       union smb_read *rd = req->async_states->private_data;
 
        switch (rd->generic.level) {
        case RAW_READ_READX:
-               nbench_log(private, "ReadX %d %d %d %d %s\n", 
+               nbench_log(nprivates, "ReadX %d %d %d %d %s\n", 
                           rd->readx.in.fnum, 
                           (int)rd->readx.in.offset,
                           rd->readx.in.maxcnt,
                           rd->readx.out.nread,
-                          get_nt_error_c_code(status));
+                          get_nt_error_c_code(req->async_states->status));
                break;
        default:
-               nbench_log(private, "Read-%d - NOT HANDLED\n",
+               nbench_log(nprivates, "Read-%d - NOT HANDLED\n",
                           rd->generic.level);
                break;
        }
 
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_read(struct ntvfs_module_context *ntvfs,
+                           struct smbsrv_request *req, union smb_read *rd)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, read, rd, (ntvfs, req, rd));
+
        return status;
 }
 
 /*
   write to a file
 */
-static NTSTATUS nbench_write(struct ntvfs_module_context *ntvfs,
-                            struct smbsrv_request *req, union smb_write *wr)
+static void nbench_write_send(struct smbsrv_request *req)
 {
-       struct nbench_private *private = ntvfs->private_data;
-       NTSTATUS status;
-
-       PASS_THRU_REQ(ntvfs, req, write, (ntvfs, req, wr));
+       PASS_THRU_REP_PRE(req);
+       union smb_write *wr = req->async_states->private_data;
 
        switch (wr->generic.level) {
        case RAW_WRITE_WRITEX:
-               nbench_log(private, "WriteX %d %d %d %d %s\n", 
+               nbench_log(nprivates, "WriteX %d %d %d %d %s\n", 
                           wr->writex.in.fnum, 
                           (int)wr->writex.in.offset,
                           wr->writex.in.count,
                           wr->writex.out.nwritten,
-                          get_nt_error_c_code(status));
+                          get_nt_error_c_code(req->async_states->status));
                break;
 
        case RAW_WRITE_WRITE:
-               nbench_log(private, "Write %d %d %d %d %s\n", 
+               nbench_log(nprivates, "Write %d %d %d %d %s\n", 
                           wr->write.in.fnum, 
                           wr->write.in.offset,
                           wr->write.in.count,
                           wr->write.out.nwritten,
-                          get_nt_error_c_code(status));
+                          get_nt_error_c_code(req->async_states->status));
                break;
 
        default:
-               nbench_log(private, "Write-%d - NOT HANDLED\n",
+               nbench_log(nprivates, "Write-%d - NOT HANDLED\n",
                           wr->generic.level);
                break;
        }
 
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_write(struct ntvfs_module_context *ntvfs,
+                            struct smbsrv_request *req, union smb_write *wr)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, write, wr, (ntvfs, req, wr));
+
        return status;
 }
 
 /*
   seek in a file
 */
+static void nbench_seek_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+
+       nbench_log(nprivates, "Seek - NOT HANDLED\n");
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_seek(struct ntvfs_module_context *ntvfs,
                            struct smbsrv_request *req, struct smb_seek *io)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, seek, (ntvfs, req, io));
-
-       nbench_log(private, "Seek - NOT HANDLED\n");
+       PASS_THRU_REQ(ntvfs, req, seek, io, (ntvfs, req, io));
 
        return status;
 }
@@ -419,17 +538,24 @@ static NTSTATUS nbench_seek(struct ntvfs_module_context *ntvfs,
 /*
   flush a file
 */
+static void nbench_flush_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+       struct smb_flush *io = req->async_states->private_data;
+
+       nbench_log(nprivates, "Flush %d %s\n",
+                  io->in.fnum,
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_flush(struct ntvfs_module_context *ntvfs,
                             struct smbsrv_request *req, struct smb_flush *io)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, flush, (ntvfs, req, io));
-
-       nbench_log(private, "Flush %d %s\n",
-                  io->in.fnum,
-                  get_nt_error_c_code(status));
+       PASS_THRU_REQ(ntvfs, req, flush, io, (ntvfs, req, io));
 
        return status;
 }
@@ -437,39 +563,55 @@ static NTSTATUS nbench_flush(struct ntvfs_module_context *ntvfs,
 /*
   close a file
 */
-static NTSTATUS nbench_close(struct ntvfs_module_context *ntvfs,
-                            struct smbsrv_request *req, union smb_close *io)
+static void nbench_close_send(struct smbsrv_request *req)
 {
-       struct nbench_private *private = ntvfs->private_data;
-       NTSTATUS status;
-
-       PASS_THRU_REQ(ntvfs, req, close, (ntvfs, req, io));
+       PASS_THRU_REP_PRE(req);
+       union smb_close *io = req->async_states->private_data;
 
        switch (io->generic.level) {
        case RAW_CLOSE_CLOSE:
-               nbench_log(private, "Close %d %s\n",
+               nbench_log(nprivates, "Close %d %s\n",
                           io->close.in.fnum,
-                          get_nt_error_c_code(status));
+                          get_nt_error_c_code(req->async_states->status));
                break;
 
        default:
-               nbench_log(private, "Close-%d - NOT HANDLED\n",
+               nbench_log(nprivates, "Close-%d - NOT HANDLED\n",
                           io->generic.level);
                break;
        }               
 
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_close(struct ntvfs_module_context *ntvfs,
+                            struct smbsrv_request *req, union smb_close *io)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, close, io, (ntvfs, req, io));
+
        return status;
 }
 
 /*
   exit - closing files
 */
+static void nbench_exit_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+
+       nbench_log(nprivates, "Exit - NOT HANDLED\n");
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_exit(struct ntvfs_module_context *ntvfs,
                            struct smbsrv_request *req)
 {
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, exit, (ntvfs, req));
+       PASS_THRU_REQ(ntvfs, req, exit, NULL, (ntvfs, req));
 
        return status;
 }
@@ -477,12 +619,21 @@ static NTSTATUS nbench_exit(struct ntvfs_module_context *ntvfs,
 /*
   logoff - closing files
 */
+static void nbench_logoff_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+
+       nbench_log(nprivates, "Logoff - NOT HANDLED\n");
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_logoff(struct ntvfs_module_context *ntvfs,
                              struct smbsrv_request *req)
 {
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, logoff, (ntvfs, req));
+       PASS_THRU_REQ(ntvfs, req, logoff, NULL, (ntvfs, req));
 
        return status;
 }
@@ -500,71 +651,91 @@ static NTSTATUS nbench_async_setup(struct ntvfs_module_context *ntvfs,
 /*
   lock a byte range
 */
-static NTSTATUS nbench_lock(struct ntvfs_module_context *ntvfs,
-                           struct smbsrv_request *req, union smb_lock *lck)
+static void nbench_lock_send(struct smbsrv_request *req)
 {
-       struct nbench_private *private = ntvfs->private_data;
-       NTSTATUS status;
-
-       PASS_THRU_REQ(ntvfs, req, lock, (ntvfs, req, lck));
+       PASS_THRU_REP_PRE(req);
+       union smb_lock *lck = req->async_states->private_data;
 
        if (lck->generic.level == RAW_LOCK_LOCKX &&
            lck->lockx.in.lock_cnt == 1 &&
            lck->lockx.in.ulock_cnt == 0) {
-               nbench_log(private, "LockX %d %d %d %s\n", 
+               nbench_log(nprivates, "LockX %d %d %d %s\n", 
                           lck->lockx.in.fnum,
                           (int)lck->lockx.in.locks[0].offset,
                           (int)lck->lockx.in.locks[0].count,
-                          get_nt_error_c_code(status));
+                          get_nt_error_c_code(req->async_states->status));
        } else if (lck->generic.level == RAW_LOCK_LOCKX &&
                   lck->lockx.in.ulock_cnt == 1) {
-               nbench_log(private, "UnlockX %d %d %d %s\n", 
+               nbench_log(nprivates, "UnlockX %d %d %d %s\n", 
                           lck->lockx.in.fnum,
                           (int)lck->lockx.in.locks[0].offset,
                           (int)lck->lockx.in.locks[0].count,
-                          get_nt_error_c_code(status));
+                          get_nt_error_c_code(req->async_states->status));
        } else {
-               nbench_log(private, "Lock-%d - NOT HANDLED\n", lck->generic.level);
+               nbench_log(nprivates, "Lock-%d - NOT HANDLED\n", lck->generic.level);
        }
 
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_lock(struct ntvfs_module_context *ntvfs,
+                           struct smbsrv_request *req, union smb_lock *lck)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, lock, lck, (ntvfs, req, lck));
+
        return status;
 }
 
 /*
   set info on a open file
 */
+static void nbench_setfileinfo_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+       union smb_setfileinfo *info = req->async_states->private_data;
+
+       nbench_log(nprivates, "SET_FILE_INFORMATION %d %d %s\n", 
+                  info->generic.file.fnum,
+                  info->generic.level,
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_setfileinfo(struct ntvfs_module_context *ntvfs,
                                   struct smbsrv_request *req, 
                                   union smb_setfileinfo *info)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, setfileinfo, (ntvfs, req, info));
-
-       nbench_log(private, "SET_FILE_INFORMATION %d %d %s\n", 
-                  info->generic.file.fnum,
-                  info->generic.level,
-                  get_nt_error_c_code(status));
+       PASS_THRU_REQ(ntvfs, req, setfileinfo, info, (ntvfs, req, info));
 
        return status;
 }
 
-
 /*
   return filesystem space info
 */
+static void nbench_fsinfo_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+       union smb_fsinfo *fs = req->async_states->private_data;
+
+       nbench_log(nprivates, "QUERY_FS_INFORMATION %d %s\n", 
+                  fs->generic.level, 
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_fsinfo(struct ntvfs_module_context *ntvfs,
                              struct smbsrv_request *req, union smb_fsinfo *fs)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, fsinfo, (ntvfs, req, fs));
-
-       nbench_log(private, "QUERY_FS_INFORMATION %d %s\n", 
-                  fs->generic.level, 
-                  get_nt_error_c_code(status));
+       PASS_THRU_REQ(ntvfs, req, fsinfo, fs, (ntvfs, req, fs));
 
        return status;
 }
@@ -572,15 +743,22 @@ static NTSTATUS nbench_fsinfo(struct ntvfs_module_context *ntvfs,
 /*
   return print queue info
 */
+static void nbench_lpq_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+       union smb_lpq *lpq = req->async_states->private_data;
+
+       nbench_log(nprivates, "Lpq-%d - NOT HANDLED\n", lpq->generic.level);
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_lpq(struct ntvfs_module_context *ntvfs,
                           struct smbsrv_request *req, union smb_lpq *lpq)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, lpq, (ntvfs, req, lpq));
-
-       nbench_log(private, "Lpq-%d - NOT HANDLED\n", lpq->generic.level);
+       PASS_THRU_REQ(ntvfs, req, lpq, lpq, (ntvfs, req, lpq));
 
        return status;
 }
@@ -588,74 +766,101 @@ static NTSTATUS nbench_lpq(struct ntvfs_module_context *ntvfs,
 /* 
    list files in a directory matching a wildcard pattern
 */
-static NTSTATUS nbench_search_first(struct ntvfs_module_context *ntvfs,
-                                   struct smbsrv_request *req, union smb_search_first *io, 
-                                   void *search_private, 
-                                   BOOL (*callback)(void *, union smb_search_data *))
+static void nbench_search_first_send(struct smbsrv_request *req)
 {
-       struct nbench_private *private = ntvfs->private_data;
-       NTSTATUS status;
-
-       PASS_THRU_REQ(ntvfs, req, search_first, (ntvfs, req, io, search_private, callback));
-
+       PASS_THRU_REP_PRE(req);
+       union smb_search_first *io = req->async_states->private_data;
+       
        switch (io->generic.level) {
        case RAW_SEARCH_BOTH_DIRECTORY_INFO:
-               nbench_log(private, "FIND_FIRST \"%s\" %d %d %d %s\n", 
+               nbench_log(nprivates, "FIND_FIRST \"%s\" %d %d %d %s\n", 
                           io->t2ffirst.in.pattern,
                           io->generic.level,
                           io->t2ffirst.in.max_count,
                           io->t2ffirst.out.count,
-                          get_nt_error_c_code(status));
+                          get_nt_error_c_code(req->async_states->status));
                break;
                
        default:
-               nbench_log(private, "Search-%d - NOT HANDLED\n", io->generic.level);
+               nbench_log(nprivates, "Search-%d - NOT HANDLED\n", io->generic.level);
                break;
        }
 
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_search_first(struct ntvfs_module_context *ntvfs,
+                                   struct smbsrv_request *req, union smb_search_first *io, 
+                                   void *search_private, 
+                                   BOOL (*callback)(void *, union smb_search_data *))
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, search_first, io, (ntvfs, req, io, search_private, callback));
+
        return status;
 }
 
 /* continue a search */
+static void nbench_search_next_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+       union smb_search_next *io = req->async_states->private_data;
+
+       nbench_log(nprivates, "Searchnext-%d - NOT HANDLED\n", io->generic.level);
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_search_next(struct ntvfs_module_context *ntvfs,
                                   struct smbsrv_request *req, union smb_search_next *io, 
                                   void *search_private, 
                                   BOOL (*callback)(void *, union smb_search_data *))
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, search_next, (ntvfs, req, io, search_private, callback));
-
-       nbench_log(private, "Searchnext-%d - NOT HANDLED\n", io->generic.level);
+       PASS_THRU_REQ(ntvfs, req, search_next, io, (ntvfs, req, io, search_private, callback));
 
        return status;
 }
 
 /* close a search */
+static void nbench_search_close_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+       union smb_search_close *io = req->async_states->private_data;
+
+       nbench_log(nprivates, "Searchclose-%d - NOT HANDLED\n", io->generic.level);
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_search_close(struct ntvfs_module_context *ntvfs,
                                    struct smbsrv_request *req, union smb_search_close *io)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, search_close, (ntvfs, req, io));
-
-       nbench_log(private, "Searchclose-%d - NOT HANDLED\n", io->generic.level);
+       PASS_THRU_REQ(ntvfs, req, search_close, io, (ntvfs, req, io));
 
        return status;
 }
 
 /* SMBtrans - not used on file shares */
+static void nbench_trans_send(struct smbsrv_request *req)
+{
+       PASS_THRU_REP_PRE(req);
+
+       nbench_log(nprivates, "Trans - NOT HANDLED\n");
+
+       PASS_THRU_REP_POST(req);
+}
+
 static NTSTATUS nbench_trans(struct ntvfs_module_context *ntvfs,
                             struct smbsrv_request *req, struct smb_trans2 *trans2)
 {
-       struct nbench_private *private = ntvfs->private_data;
        NTSTATUS status;
 
-       PASS_THRU_REQ(ntvfs, req, trans, (ntvfs, req, trans2));
-
-       nbench_log(private, "Trans - NOT HANDLED\n");
+       PASS_THRU_REQ(ntvfs, req, trans, trans2, (ntvfs, req, trans2));
 
        return status;
 }
index c9fe276f5441850d235e98d438bbbcaa10414660..04e9b871c72233308e5cfb124135c3f5f4f144b1 100644 (file)
@@ -134,12 +134,45 @@ struct ntvfs_context {
        struct ntvfs_module_context *modules;
 };
 
+
+/* a set of flags to control handling of request structures */
+#define NTVFS_ASYNC_STATE_ASYNC     (1<<1) /* the backend will answer this one later */
+#define NTVFS_ASYNC_STATE_MAY_ASYNC (1<<2) /* the backend is allowed to answer async */
+
+/* the ntvfs_async_state structure allows backend functions to 
+   delay replying to requests. To use this, the front end must
+   set send_fn to a function to be called by the backend
+   when the reply is finally ready to be sent. The backend
+   must set status to the status it wants in the
+   reply. The backend must set the NTVFS_ASYNC_STATE_ASYNC
+   control_flag on the request to indicate that it wishes to
+   delay the reply
+
+   If NTVFS_ASYNC_STATE_MAY_ASYNC is not set then the backend cannot
+   ask for a delayed reply for this request
+
+   note that the private_data pointer is private to the layer which alloced this struct
+*/
+struct ntvfs_async_state {
+       struct ntvfs_async_state *prev, *next;
+       /* the async handling infos */
+       unsigned state;
+       void *private_data;
+       void (*send_fn)(struct smbsrv_request *);
+       NTSTATUS status;
+
+       /* the passthru module's per session private data */
+       struct ntvfs_module_context *ntvfs;
+};
+
 /* this structure is used by backends to determine the size of some critical types */
 struct ntvfs_critical_sizes {
        int interface_version;
+       int sizeof_ntvfs_critical_sizes;
        int sizeof_ntvfs_context;
        int sizeof_ntvfs_module_context;
        int sizeof_ntvfs_ops;
+       int sizeof_ntvfs_async_state;
        int sizeof_smbsrv_tcon;
        int sizeof_smbsrv_request;
 };
index acbd02d9151bbf75598d98ab00157294180f9af7..17900b3dfcf09ce775d3c6f7bdf401985e3a72c6 100644 (file)
@@ -100,9 +100,11 @@ const struct ntvfs_critical_sizes *ntvfs_interface_version(void)
 {
        static const struct ntvfs_critical_sizes critical_sizes = {
                NTVFS_INTERFACE_VERSION,
+               sizeof(struct ntvfs_critical_sizes),
                sizeof(struct ntvfs_context),
                sizeof(struct ntvfs_module_context),
                sizeof(struct ntvfs_ops),
+               sizeof(struct ntvfs_async_state),
                sizeof(struct smbsrv_tcon),
                sizeof(struct smbsrv_request),
        };
index 452273cbdb2dfc23677923cc3fa185d32951b1f9..2639b5ae396d5fdbcef79ae6bba395efed9ed8fc 100644 (file)
@@ -71,7 +71,7 @@ NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io,
 
        /* must be synchronous, or we won't be called to do the 
           translation */
-       req->control_flags &= ~REQ_CONTROL_MAY_ASYNC;
+       req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
 
        switch (io->generic.level) {
        case RAW_OPEN_GENERIC:
@@ -692,7 +692,7 @@ NTSTATUS ntvfs_map_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *inf
 
        /* must be synchronous, or we won't be called to do the 
           translation */
-       req->control_flags &= ~REQ_CONTROL_MAY_ASYNC;
+       req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
 
        status = ntvfs->ops->qpathinfo(ntvfs, req, info2);
        if (!NT_STATUS_IS_OK(status)) {
@@ -768,7 +768,7 @@ NTSTATUS ntvfs_map_write(struct smbsrv_request *req, union smb_write *wr,
        wr2->generic.level = RAW_WRITE_GENERIC;
 
        /* we can't map asynchronously */
-       req->control_flags &= ~REQ_CONTROL_MAY_ASYNC;
+       req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
 
        switch (wr->generic.level) {
        case RAW_WRITE_WRITEX:
@@ -874,7 +874,7 @@ NTSTATUS ntvfs_map_read(struct smbsrv_request *req, union smb_read *rd,
        rd2->generic.level = RAW_READ_GENERIC;
 
        /* we can't map asynchronously */
-       req->control_flags &= ~REQ_CONTROL_MAY_ASYNC;
+       req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;
 
        switch (rd->generic.level) {
        case RAW_READ_READX:
index 4036fb0935cfe380830c36c65dc6c0db6b2fce26..929ec037de182cb26d17ba435bc923bf07d4364a 100644 (file)
@@ -1,7 +1,7 @@
 /* 
    Unix SMB/CIFS implementation.
    NTVFS utility code
-   Copyright (C) Andrew Tridgell 2003
+   Copyright (C) Stefan Metzmacher 2004
 
    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
 
 #include "includes.h"
 
+NTSTATUS ntvfs_async_state_push(struct smbsrv_request *req,
+                               void *private_data,
+                               void (*send_fn)(struct smbsrv_request *),
+                               struct ntvfs_module_context *ntvfs)
+{
+       struct ntvfs_async_state *async;
 
+       async = talloc_p(req, struct ntvfs_async_state);
+       if (!async) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       async->state            = req->async_states->state;
+       async->private_data     = private_data;
+       async->send_fn          = send_fn;
+       async->status           = NT_STATUS_INTERNAL_ERROR;
+
+       async->ntvfs            = ntvfs;
+
+       DLIST_ADD(req->async_states, async);
+
+       return NT_STATUS_OK;
+}
+
+void ntvfs_async_state_pop(struct smbsrv_request *req)
+{
+       struct ntvfs_async_state *async;
+
+       async = req->async_states;
+
+       DLIST_REMOVE(req->async_states, async);
+
+       req->async_states->state        = async->state;
+       req->async_states->status       = async->status;
+
+       talloc_free(async);
+}
index 4a4da34b609e45b447b69e643d3c17fa496eee06..3835c9319b2f55d8635ff3ad8c6c777b5ebb6317 100644 (file)
@@ -77,8 +77,8 @@ static void pvfs_lock_async_failed(struct pvfs_state *pvfs,
                           locks[i].count);
                f->lock_count--;
        }
-       req->async.status = status;
-       req->async.send_fn(req);
+       req->async_states->status = status;
+       req->async_states->send_fn(req);
 }
 
 
@@ -192,8 +192,8 @@ static void pvfs_pending_lock_continue(void *private, BOOL timed_out)
        }
 
        /* we've managed to get all the locks. Tell the client */
-       req->async.status = NT_STATUS_OK;
-       req->async.send_fn(req);
+       req->async_states->status = NT_STATUS_OK;
+       req->async_states->send_fn(req);
 }
 
 
@@ -217,8 +217,8 @@ void pvfs_lock_close(struct pvfs_state *pvfs, struct pvfs_file *f)
                next = p->next;
                DLIST_REMOVE(f->pending_list, p);
                talloc_free(p->wait_handle);
-               p->req->async.status = NT_STATUS_RANGE_NOT_LOCKED;
-               p->req->async.send_fn(p->req);
+               p->req->async_states->status = NT_STATUS_RANGE_NOT_LOCKED;
+               p->req->async_states->send_fn(p->req);
        }
 }
 
@@ -287,7 +287,7 @@ NTSTATUS pvfs_lock(struct ntvfs_module_context *ntvfs,
        }
 
        if (lck->lockx.in.timeout != 0 && 
-           (req->control_flags & REQ_CONTROL_MAY_ASYNC)) {
+           (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) {
                pending = talloc_p(req, struct pvfs_pending_lock);
                if (pending == NULL) {
                        return NT_STATUS_NO_MEMORY;
index 071ecbce15ffcb1397a94a4af0509e5489a6b3ca..2a8cbbbe0d321f84bf17abdb74abaf71fb3af94f 100644 (file)
@@ -149,7 +149,7 @@ void *pvfs_wait_message(struct pvfs_state *pvfs,
 
        /* tell the main smb server layer that we will be replying 
           asynchronously */
-       req->control_flags |= REQ_CONTROL_ASYNC;
+       req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC;
 
        /* make sure we cleanup the timer and message handler */
        talloc_set_destructor(pwait, pvfs_wait_destructor);
index fbf683e38126a5a70afa3749e2687531e69b7863..dd1df29573d97350d13612f6bdebbdac89588540 100644 (file)
                return; \
        }} while (0)
 
-/* check req->async.status and if not OK then send an error reply */
+/* check req->async_states->status and if not OK then send an error reply */
 #define CHECK_ASYNC_STATUS do { \
-       if (!NT_STATUS_IS_OK(req->async.status)) { \
-               req_reply_error(req, req->async.status); \
+       if (!NT_STATUS_IS_OK(req->async_states->status)) { \
+               req_reply_error(req, req->async_states->status); \
                return; \
        }} while (0)
        
@@ -55,8 +55,8 @@
    immediately
 */
 #define REQ_ASYNC_TAIL do { \
-       if (!(req->control_flags & REQ_CONTROL_ASYNC)) { \
-               req->async.send_fn(req); \
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
+               req->async_states->send_fn(req); \
        }} while (0)
 
 /* zero out some reserved fields in a reply */
@@ -206,7 +206,7 @@ void reply_unknown(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_ioctl_send(struct smbsrv_request *req)
 {
-       union smb_ioctl *io = req->async.private;
+       union smb_ioctl *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -236,12 +236,12 @@ void reply_ioctl(struct smbsrv_request *req)
        io->ioctl.in.fnum     = req_fnum(req, req->in.vwv, VWV(0));
        io->ioctl.in.request  = IVAL(req->in.vwv, VWV(1));
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_ioctl_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_ioctl_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = ntvfs_ioctl(req, io);
+       req->async_states->status = ntvfs_ioctl(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -258,10 +258,10 @@ void reply_chkpth(struct smbsrv_request *req)
 
        req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
-       req->async.status = ntvfs_chkpath(req, io);
+       req->async_states->status = ntvfs_chkpath(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -271,7 +271,7 @@ void reply_chkpth(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_getatr_send(struct smbsrv_request *req)
 {
-       union smb_fileinfo *st = req->async.private;
+       union smb_fileinfo *st = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
        
@@ -306,12 +306,12 @@ void reply_getatr(struct smbsrv_request *req)
                return;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_getatr_send;
-       req->async.private = st;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_getatr_send;
+       req->async_states->private_data = st;
 
        /* call backend */
-       req->async.status = ntvfs_qpathinfo(req, st);
+       req->async_states->status = ntvfs_qpathinfo(req, st);
 
        REQ_ASYNC_TAIL;
 }
@@ -339,11 +339,11 @@ void reply_setatr(struct smbsrv_request *req)
                return;
        }
        
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = ntvfs_setpathinfo(req, st);
+       req->async_states->status = ntvfs_setpathinfo(req, st);
 
        REQ_ASYNC_TAIL;
 }
@@ -354,7 +354,7 @@ void reply_setatr(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_dskattr_send(struct smbsrv_request *req)
 {
-       union smb_fsinfo *fs = req->async.private;
+       union smb_fsinfo *fs = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
        
@@ -383,12 +383,12 @@ void reply_dskattr(struct smbsrv_request *req)
        
        fs->dskattr.level = RAW_QFS_DSKATTR;
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_dskattr_send;
-       req->async.private = fs;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_dskattr_send;
+       req->async_states->private_data = fs;
 
        /* call backend */
-       req->async.status = ntvfs_fsinfo(req, fs);
+       req->async_states->status = ntvfs_fsinfo(req, fs);
 
        REQ_ASYNC_TAIL;
 }
@@ -400,7 +400,7 @@ void reply_dskattr(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_open_send(struct smbsrv_request *req)
 {
-       union smb_open *oi = req->async.private;
+       union smb_open *oi = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -438,12 +438,12 @@ void reply_open(struct smbsrv_request *req)
                return;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_open_send;
-       req->async.private = oi;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_open_send;
+       req->async_states->private_data = oi;
        
        /* call backend */
-       req->async.status = ntvfs_open(req, oi);
+       req->async_states->status = ntvfs_open(req, oi);
 
        REQ_ASYNC_TAIL;
 }
@@ -454,7 +454,7 @@ void reply_open(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_open_and_X_send(struct smbsrv_request *req)
 {
-       union smb_open *oi = req->async.private;
+       union smb_open *oi = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -514,12 +514,12 @@ void reply_open_and_X(struct smbsrv_request *req)
                return;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_open_and_X_send;
-       req->async.private = oi;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_open_and_X_send;
+       req->async_states->private_data = oi;
 
        /* call the backend */
-       req->async.status = ntvfs_open(req, oi);
+       req->async_states->status = ntvfs_open(req, oi);
 
        REQ_ASYNC_TAIL;
 }
@@ -530,7 +530,7 @@ void reply_open_and_X(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_mknew_send(struct smbsrv_request *req)
 {
-       union smb_open *oi = req->async.private;
+       union smb_open *oi = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -565,12 +565,12 @@ void reply_mknew(struct smbsrv_request *req)
                return;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_mknew_send;
-       req->async.private = oi;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_mknew_send;
+       req->async_states->private_data = oi;
 
        /* call the backend */
-       req->async.status = ntvfs_open(req, oi);
+       req->async_states->status = ntvfs_open(req, oi);
 
        REQ_ASYNC_TAIL;
 }
@@ -580,7 +580,7 @@ void reply_mknew(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_ctemp_send(struct smbsrv_request *req)
 {
-       union smb_open *oi = req->async.private;
+       union smb_open *oi = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -619,12 +619,12 @@ void reply_ctemp(struct smbsrv_request *req)
                return;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_ctemp_send;
-       req->async.private = oi;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_ctemp_send;
+       req->async_states->private_data = oi;
 
        /* call the backend */
-       req->async.status = ntvfs_open(req, oi);
+       req->async_states->status = ntvfs_open(req, oi);
 
        REQ_ASYNC_TAIL;
 }
@@ -645,11 +645,11 @@ void reply_unlink(struct smbsrv_request *req)
 
        req_pull_ascii4(req, &unl->in.pattern, req->in.data, STR_TERMINATE);
        
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = ntvfs_unlink(req, unl);
+       req->async_states->status = ntvfs_unlink(req, unl);
 
        REQ_ASYNC_TAIL;
 }
@@ -724,7 +724,7 @@ failed:
 ****************************************************************************/
 static void reply_lockread_send(struct smbsrv_request *req)
 {
-       union smb_read *io = req->async.private;
+       union smb_read *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -768,12 +768,12 @@ void reply_lockread(struct smbsrv_request *req)
        /* tell the backend where to put the data */
        io->lockread.out.data = req->out.data + 3;
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_lockread_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_lockread_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = ntvfs_read(req, io);
+       req->async_states->status = ntvfs_read(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -785,7 +785,7 @@ void reply_lockread(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_read_send(struct smbsrv_request *req)
 {
-       union smb_read *io = req->async.private;
+       union smb_read *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -827,12 +827,12 @@ void reply_read(struct smbsrv_request *req)
        /* tell the backend where to put the data */
        io->read.out.data = req->out.data + 3;
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_read_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_read_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = ntvfs_read(req, io);
+       req->async_states->status = ntvfs_read(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -844,7 +844,7 @@ void reply_read(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_read_and_X_send(struct smbsrv_request *req)
 {
-       union smb_read *io = req->async.private;
+       union smb_read *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -910,12 +910,12 @@ void reply_read_and_X(struct smbsrv_request *req)
                io->readx.out.data = req->out.data;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_read_and_X_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_read_and_X_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = ntvfs_read(req, io);
+       req->async_states->status = ntvfs_read(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -936,7 +936,7 @@ void reply_writebraw(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_writeunlock_send(struct smbsrv_request *req)
 {
-       union smb_write *io = req->async.private;
+       union smb_write *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -977,12 +977,12 @@ void reply_writeunlock(struct smbsrv_request *req)
                return;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_writeunlock_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_writeunlock_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = ntvfs_write(req, io);
+       req->async_states->status = ntvfs_write(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -994,7 +994,7 @@ void reply_writeunlock(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_write_send(struct smbsrv_request *req)
 {
-       union smb_write *io = req->async.private;
+       union smb_write *io = req->async_states->private_data;
        
        CHECK_ASYNC_STATUS;
 
@@ -1035,12 +1035,12 @@ void reply_write(struct smbsrv_request *req)
                return;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_write_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_write_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = ntvfs_write(req, io);
+       req->async_states->status = ntvfs_write(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1051,7 +1051,7 @@ void reply_write(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_write_and_X_send(struct smbsrv_request *req)
 {
-       union smb_write *io = req->async.private;
+       union smb_write *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -1102,12 +1102,12 @@ void reply_write_and_X(struct smbsrv_request *req)
                return;
        } 
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_write_and_X_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_write_and_X_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = ntvfs_write(req, io);
+       req->async_states->status = ntvfs_write(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1118,7 +1118,7 @@ void reply_write_and_X(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_lseek_send(struct smbsrv_request *req)
 {
-       struct smb_seek *io = req->async.private;
+       struct smb_seek *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -1144,12 +1144,12 @@ void reply_lseek(struct smbsrv_request *req)
        io->in.mode   = SVAL(req->in.vwv,  VWV(1));
        io->in.offset = IVALS(req->in.vwv, VWV(2));
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_lseek_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_lseek_send;
+       req->async_states->private_data = io;
        
        /* call backend */
-       req->async.status = ntvfs_seek(req, io);
+       req->async_states->status = ntvfs_seek(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1167,11 +1167,11 @@ void reply_flush(struct smbsrv_request *req)
 
        io->in.fnum   = req_fnum(req, req->in.vwv,  VWV(0));
        
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = ntvfs_flush(req, io);
+       req->async_states->status = ntvfs_flush(req, io);
        
        REQ_ASYNC_TAIL;
 }
@@ -1218,11 +1218,11 @@ void reply_close(struct smbsrv_request *req)
        io->close.in.fnum  = req_fnum(req, req->in.vwv,  VWV(0));
        io->close.in.write_time = srv_pull_dos_date3(req->smb_conn, req->in.vwv + VWV(1));
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = ntvfs_close(req, io);
+       req->async_states->status = ntvfs_close(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1234,7 +1234,7 @@ void reply_close(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_writeclose_send(struct smbsrv_request *req)
 {
-       union smb_write *io = req->async.private;
+       union smb_write *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -1273,12 +1273,12 @@ void reply_writeclose(struct smbsrv_request *req)
                return;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_writeclose_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_writeclose_send;
+       req->async_states->private_data = io;
 
        /* call backend */
-       req->async.status = ntvfs_write(req, io);
+       req->async_states->status = ntvfs_write(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1299,11 +1299,11 @@ void reply_lock(struct smbsrv_request *req)
        lck->lock.in.count  = IVAL(req->in.vwv, VWV(1));
        lck->lock.in.offset = IVAL(req->in.vwv, VWV(3));
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = ntvfs_lock(req, lck);
+       req->async_states->status = ntvfs_lock(req, lck);
 
        REQ_ASYNC_TAIL;
 }
@@ -1325,11 +1325,11 @@ void reply_unlock(struct smbsrv_request *req)
        lck->unlock.in.count  = IVAL(req->in.vwv, VWV(1));
        lck->unlock.in.offset = IVAL(req->in.vwv, VWV(3));
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = ntvfs_lock(req, lck);
+       req->async_states->status = ntvfs_lock(req, lck);
 
        REQ_ASYNC_TAIL;
 }
@@ -1385,7 +1385,7 @@ void reply_echo(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_printopen_send(struct smbsrv_request *req)
 {
-       union smb_open *oi = req->async.private;
+       union smb_open *oi = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -1414,12 +1414,12 @@ void reply_printopen(struct smbsrv_request *req)
 
        req_pull_ascii4(req, &oi->splopen.in.ident, req->in.data, STR_TERMINATE);
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_printopen_send;
-       req->async.private = oi;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_printopen_send;
+       req->async_states->private_data = oi;
 
        /* call backend */
-       req->async.status = ntvfs_open(req, oi);
+       req->async_states->status = ntvfs_open(req, oi);
 
        REQ_ASYNC_TAIL;
 }
@@ -1438,11 +1438,11 @@ void reply_printclose(struct smbsrv_request *req)
        io->splclose.level = RAW_CLOSE_SPLCLOSE;
        io->splclose.in.fnum = req_fnum(req, req->in.vwv,  VWV(0));
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = ntvfs_close(req, io);
+       req->async_states->status = ntvfs_close(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1452,7 +1452,7 @@ void reply_printclose(struct smbsrv_request *req)
 ****************************************************************************/
 void reply_printqueue_send(struct smbsrv_request *req)
 {
-       union smb_lpq *lpq = req->async.private;
+       union smb_lpq *lpq = req->async_states->private_data;
        int i, maxcount;
        const uint_t el_size = 28;      
 
@@ -1507,12 +1507,12 @@ void reply_printqueue(struct smbsrv_request *req)
        lpq->retq.in.maxcount = SVAL(req->in.vwv,  VWV(0));
        lpq->retq.in.startidx = SVAL(req->in.vwv,  VWV(1));
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_printqueue_send;
-       req->async.private = lpq;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_printqueue_send;
+       req->async_states->private_data = lpq;
 
        /* call backend */
-       req->async.status = ntvfs_lpq(req, lpq);
+       req->async_states->status = ntvfs_lpq(req, lpq);
 
        REQ_ASYNC_TAIL;
 }
@@ -1546,11 +1546,11 @@ void reply_printwrite(struct smbsrv_request *req)
                return;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = ntvfs_write(req, io);
+       req->async_states->status = ntvfs_write(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1570,11 +1570,11 @@ void reply_mkdir(struct smbsrv_request *req)
        io->generic.level = RAW_MKDIR_MKDIR;
        req_pull_ascii4(req, &io->mkdir.in.path, req->in.data, STR_TERMINATE);
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = ntvfs_mkdir(req, io);
+       req->async_states->status = ntvfs_mkdir(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1593,11 +1593,11 @@ void reply_rmdir(struct smbsrv_request *req)
 
        req_pull_ascii4(req, &io->in.path, req->in.data, STR_TERMINATE);
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = ntvfs_rmdir(req, io);
+       req->async_states->status = ntvfs_rmdir(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1627,11 +1627,11 @@ void reply_mv(struct smbsrv_request *req)
                return;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = ntvfs_rename(req, io);
+       req->async_states->status = ntvfs_rename(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1663,11 +1663,11 @@ void reply_ntrename(struct smbsrv_request *req)
                return;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = ntvfs_rename(req, io);
+       req->async_states->status = ntvfs_rename(req, io);
 
        REQ_ASYNC_TAIL;
 }
@@ -1677,7 +1677,7 @@ void reply_ntrename(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_copy_send(struct smbsrv_request *req)
 {
-       struct smb_copy *cp = req->async.private;
+       struct smb_copy *cp = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -1714,12 +1714,12 @@ void reply_copy(struct smbsrv_request *req)
                return;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_copy_send;
-       req->async.private = cp;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_copy_send;
+       req->async_states->private_data = cp;
 
        /* call backend */
-       req->async.status = ntvfs_copy(req, cp);
+       req->async_states->status = ntvfs_copy(req, cp);
 
        REQ_ASYNC_TAIL;
 }
@@ -1729,7 +1729,7 @@ void reply_copy(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_lockingX_send(struct smbsrv_request *req)
 {
-       union smb_lock *lck = req->async.private;
+       union smb_lock *lck = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -1815,12 +1815,12 @@ void reply_lockingX(struct smbsrv_request *req)
                p += lck_size;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_lockingX_send;
-       req->async.private = lck;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_lockingX_send;
+       req->async_states->private_data = lck;
 
        /* call backend */
-       req->async.status = ntvfs_lock(req, lck);
+       req->async_states->status = ntvfs_lock(req, lck);
 
        REQ_ASYNC_TAIL;
 }
@@ -1852,11 +1852,11 @@ void reply_setattrE(struct smbsrv_request *req)
        info->setattre.in.access_time = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(3));
        info->setattre.in.write_time  = srv_pull_dos_date2(req->smb_conn, req->in.vwv + VWV(5));
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_simple_send;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_simple_send;
 
        /* call backend */
-       req->async.status = ntvfs_setfileinfo(req, info);
+       req->async_states->status = ntvfs_setfileinfo(req, info);
 
        REQ_ASYNC_TAIL;
 }
@@ -1888,7 +1888,7 @@ void reply_writebs(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_getattrE_send(struct smbsrv_request *req)
 {
-       union smb_fileinfo *info = req->async.private;
+       union smb_fileinfo *info = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -1919,12 +1919,12 @@ void reply_getattrE(struct smbsrv_request *req)
        info->getattr.level = RAW_FILEINFO_GETATTRE;
        info->getattr.in.fnum = req_fnum(req, req->in.vwv, VWV(0));
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_getattrE_send;
-       req->async.private = info;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_getattrE_send;
+       req->async_states->private_data = info;
 
        /* call backend */
-       req->async.status = ntvfs_qfileinfo(req, info);
+       req->async_states->status = ntvfs_qfileinfo(req, info);
 
        REQ_ASYNC_TAIL;
 }
@@ -2224,7 +2224,7 @@ void reply_findnclose(struct smbsrv_request *req)
 ****************************************************************************/
 static void reply_ntcreate_and_X_send(struct smbsrv_request *req)
 {
-       union smb_open *io = req->async.private;
+       union smb_open *io = req->async_states->private_data;
 
        CHECK_ASYNC_STATUS;
 
@@ -2291,12 +2291,12 @@ void reply_ntcreate_and_X(struct smbsrv_request *req)
                return;
        }
 
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_ntcreate_and_X_send;
-       req->async.private = io;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_ntcreate_and_X_send;
+       req->async_states->private_data = io;
 
        /* call the backend */
-       req->async.status = ntvfs_open(req, io);
+       req->async_states->status = ntvfs_open(req, io);
 
        REQ_ASYNC_TAIL;
 }
index 3095d0b70c24f3cde9ca1994feec29d258a7ae6e..34273a63a85cd522a4a09183bfac6540ca152bd1 100644 (file)
@@ -54,7 +54,14 @@ struct smbsrv_request *init_smb_request(struct smbsrv_connection *smb_conn)
 
        /* setup the request context */
        req->smb_conn = smb_conn;
-       
+
+       req->async_states = talloc_p(req, struct ntvfs_async_state);
+       if (!req->async_states) {
+               return NULL;
+       }
+
+       ZERO_STRUCTP(req->async_states);
+
        return req;
 }
 
index fdfad5e182363c45ecf7f72a57745abd259d10b3..b7b3d10ab6d829ba28d143f5a4f9fae5fb0ca4de 100644 (file)
@@ -26,8 +26,8 @@
 
 /* check req->async.status and if not OK then send an error reply */
 #define CHECK_ASYNC_STATUS do { \
-       if (!NT_STATUS_IS_OK(req->async.status)) { \
-               req_reply_error(req, req->async.status); \
+       if (!NT_STATUS_IS_OK(req->async_states->status)) { \
+               req_reply_error(req, req->async_states->status); \
                return; \
        }} while (0)
        
@@ -37,8 +37,8 @@
    immediately
 */
 #define REQ_ASYNC_TAIL do { \
-       if (!(req->control_flags & REQ_CONTROL_ASYNC)) { \
-               req->async.send_fn(req); \
+       if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
+               req->async_states->send_fn(req); \
        }} while (0)
 
 /* useful wrapper for talloc with NO_MEMORY reply */
@@ -268,12 +268,12 @@ void reply_fclose(struct smbsrv_request *req)
        sc->fclose.in.id.client_cookie = IVAL(p, 17);
 
        /* do a search close operation */
-       req->control_flags |= REQ_CONTROL_MAY_ASYNC;
-       req->async.send_fn = reply_fclose_send;
-       req->async.private = sc;
+       req->async_states->state |= NTVFS_ASYNC_STATE_MAY_ASYNC;
+       req->async_states->send_fn = reply_fclose_send;
+       req->async_states->private_data = sc;
 
        /* call backend */
-       req->async.status = ntvfs_search_close(req, sc);
+       req->async_states->status = ntvfs_search_close(req, sc);
 
        REQ_ASYNC_TAIL;
 }
index ff83bfc80c21774e2494a225e3024fdb02fd080b..86a876554fe685ccf6803ced39339a44ce678045 100644 (file)
@@ -621,10 +621,10 @@ static void construct_reply(struct smbsrv_request *req)
                return;
        }
 
-
-       req->smbpid = SVAL(req->in.hdr,HDR_PID);        
        req->flags = CVAL(req->in.hdr, HDR_FLG);
        req->flags2 = SVAL(req->in.hdr, HDR_FLG2);
+       req->smbpid = SVAL(req->in.hdr,HDR_PID);
+       req->mid = SVAL(req->in.hdr,HDR_MID);
 
        if (!req_signing_check_incoming(req)) {
                req_reply_error(req, NT_STATUS_ACCESS_DENIED);
@@ -694,8 +694,7 @@ void chain_reply(struct smbsrv_request *req)
 
        /* the current request in the chain might have used an async reply,
           but that doesn't mean the next element needs to */
-       ZERO_STRUCT(req->async);
-       req->control_flags &= ~REQ_CONTROL_ASYNC;
+       ZERO_STRUCTP(req->async_states);
 
        switch_message(chain_cmd, req);
        return;
index 4de2aac9072e6630a879b6c182dca1f10aa4829e..065c01d6f522c1cffcf56595a37b8c6ec3a82667 100644 (file)
@@ -71,6 +71,9 @@ struct smbsrv_tcon {
        char *dev_type;
 };
 
+/* a set of flags to control handling of request structures */
+#define REQ_CONTROL_LARGE     (1<<1) /* allow replies larger than max_xmit */
+
 /* the context for a single SMB request. This is passed to any request-context 
    functions */
 struct smbsrv_request {
@@ -86,6 +89,9 @@ struct smbsrv_request {
        /* the session context is derived from the vuid */
        struct smbsrv_session *session;
 
+       /* the mid of this packet - used to match replies */
+       uint16_t mid;
+
        /* a set of flags to control usage of the request. See REQ_CONTROL_* */
        unsigned control_flags;
 
@@ -108,26 +114,8 @@ struct smbsrv_request {
        /* the sequence number for signing */
        uint64_t seq_num;
 
-       /* the async structure allows backend functions to delay
-          replying to requests. To use this, the front end must set
-          async.send_fn to a function to be called by the backend
-          when the reply is finally ready to be sent. The backend
-          must set async.status to the status it wants in the
-          reply. The backend must set the REQ_CONTROL_ASYNC
-          control_flag on the request to indicate that it wishes to
-          delay the reply
-
-          If REQ_CONTROL_MAY_ASYNC is not set then the backend cannot
-          ask for a delayed reply for this request
-
-          note that the async.private pointer is private to the front
-          end not the backend. The backend must not change it.
-       */
-       struct {
-               void (*send_fn)(struct smbsrv_request *);
-               void *private;
-               NTSTATUS status;
-       } async;
+       /* ntvfs per request async states */
+       struct ntvfs_async_state *async_states;
 
        struct request_buffer in;
        struct request_buffer out;