r23792: convert Samba4 to GPLv3
[tprouty/samba.git] / source4 / ntvfs / nbench / vfs_nbench.c
index eebf6f1dde5254ee40f819c5036fdd3a5ca6c26d..9379419c50d86a93fe9e7be4f6b5e4d1c1b8e7e9 100644 (file)
@@ -7,7 +7,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -16,8 +16,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 /*
 */
 
 #include "includes.h"
+#include "ntvfs/ntvfs.h"
+#include "system/filesys.h"
 
 /* this is stored in ntvfs_private */
 struct nbench_private {
-       const struct ntvfs_ops *passthru_ops;
        int log_fd;
 };
 
-
 /*
   log one request to the nbench log
 */
-static void nbench_log(struct nbench_private *private, 
+static void nbench_log(struct ntvfs_request *req,
                       const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
 
-static void nbench_log(struct nbench_private *private, 
+static void nbench_log(struct ntvfs_request *req,
                       const char *format, ...)
 {
+       struct nbench_private *private = req->async_states->ntvfs->private_data;
        va_list ap;
        char *s = NULL;
 
@@ -53,11 +53,25 @@ static void nbench_log(struct nbench_private *private,
        free(s);
 }
 
+static char *nbench_ntvfs_handle_string(struct ntvfs_request *req, struct ntvfs_handle *h)
+{
+       DATA_BLOB key;
+       uint16_t fnum = 0;
 
-/*
-  this is used to call the next module in the ntvfs chain
-*/
-#define PASS_THRU(tcon, op, args) private->passthru_ops->op args;
+       key = ntvfs_handle_get_wire_key(h, req);
+
+       switch (key.length) {
+       case 2: /* SMB fnum */
+               fnum = SVAL(key.data, 0);
+               break;
+       default:
+               DEBUG(0,("%s: invalid wire handle size: %u\n",
+                       __FUNCTION__, (unsigned)key.length));
+               break;
+       }
+
+       return talloc_asprintf(req, "%u", fnum);
+}
 
 /*
   this pass through macro operates on request contexts, and disables
@@ -66,51 +80,60 @@ 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(req, op, args) do { \
-       void *send_fn_saved = req->async.send_fn; \
-       req->async.send_fn = NULL; \
-       req->ntvfs_depth++; \
-       status = PASS_THRU(req->tcon, op, args); \
-       req->ntvfs_depth--; \
-       req->async.send_fn = send_fn_saved; \
+#define PASS_THRU_REQ_PRE_ASYNC(ntvfs, req, op, par1) do { \
+       status = ntvfs_async_state_push(ntvfs, req, par1, nbench_##op##_send); \
+       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)) { \
+               req->async_states->send_fn(req); \
+       } \
+} 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) { \
+               req->async_states->send_fn(req); \
+       } \
+} while (0)
 
 /*
   connect to a share - used when a tree_connect operation comes in.
 */
-static NTSTATUS nbench_connect(struct smbsrv_request *req, const char *sharename, int depth)
+static NTSTATUS nbench_connect(struct ntvfs_module_context *ntvfs,
+                              struct ntvfs_request *req, const char *sharename)
 {
-       struct nbench_private *private;
-       const char *passthru;
+       struct nbench_private *nprivates;
        NTSTATUS status;
        char *logname = NULL;
-       const char **handlers = lp_ntvfs_handler(req->tcon->service);
 
-       private = talloc_p(req->tcon, struct nbench_private);
-       if (!private) {
+       nprivates = talloc(ntvfs, struct nbench_private);
+       if (!nprivates) {
                return NT_STATUS_NO_MEMORY;
        }
 
-       asprintf(&logname, "/tmp/nbenchlog%d.%u", depth, getpid());
-       private->log_fd = open(logname, O_WRONLY|O_CREAT|O_APPEND, 0644);
+       asprintf(&logname, "/tmp/nbenchlog%d.%u", ntvfs->depth, getpid());
+       nprivates->log_fd = 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;
        }
 
-       private->passthru_ops = ntvfs_backend_byname(handlers[depth+1], NTVFS_DISK);
-
-       if (!private->passthru_ops) {
-               DEBUG(0,("Unable to connect to '%s' pass through backend\n", passthru));
-               return NT_STATUS_UNSUCCESSFUL;
-       }
+       ntvfs->private_data = nprivates;
 
-       ntvfs_set_private(req->tcon, depth, private);
-       
-       status = PASS_THRU(req->tcon, connect, (req, sharename, depth+1));
+       status = ntvfs_next_connect(ntvfs, req, sharename);
 
        return status;
 }
@@ -118,14 +141,14 @@ static NTSTATUS nbench_connect(struct smbsrv_request *req, const char *sharename
 /*
   disconnect from a share
 */
-static NTSTATUS nbench_disconnect(struct smbsrv_tcon *tcon, int depth)
+static NTSTATUS nbench_disconnect(struct ntvfs_module_context *ntvfs)
 {
-       struct nbench_private *private = tcon->ntvfs_private_list[depth];
+       struct nbench_private *nprivates = ntvfs->private_data;
        NTSTATUS status;
 
-       close(private->log_fd);
+       close(nprivates->log_fd);
 
-       status = PASS_THRU(tcon, disconnect, (tcon, depth+1));
+       status = ntvfs_next_disconnect(ntvfs);
 
        return status;
 }
@@ -134,16 +157,24 @@ static NTSTATUS nbench_disconnect(struct smbsrv_tcon *tcon, int depth)
   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 NTSTATUS nbench_unlink(struct smbsrv_request *req, struct smb_unlink *unl)
+static void nbench_unlink_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
+       union smb_unlink *unl = req->async_states->private_data;
 
-       PASS_THRU_REQ(req, unlink, (req, unl));
+       nbench_log(req, "Unlink \"%s\" 0x%x %s\n", 
+                  unl->unlink.in.pattern, unl->unlink.in.attrib, 
+                  get_nt_error_c_code(req->async_states->status));
 
-       nbench_log(private, "Unlink \"%s\" 0x%x %s\n", 
-                  unl->in.pattern, unl->in.attrib, 
-                  get_nt_error_c_code(status));
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_unlink(struct ntvfs_module_context *ntvfs,
+                             struct ntvfs_request *req,
+                             union smb_unlink *unl)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, unlink, unl, (ntvfs, req, unl));
 
        return status;
 }
@@ -151,14 +182,19 @@ static NTSTATUS nbench_unlink(struct smbsrv_request *req, struct smb_unlink *unl
 /*
   ioctl interface
 */
-static NTSTATUS nbench_ioctl(struct smbsrv_request *req, union smb_ioctl *io)
+static void nbench_ioctl_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
+       nbench_log(req, "Ioctl - NOT HANDLED\n");
 
-       PASS_THRU_REQ(req, ioctl, (req, io));
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_ioctl(struct ntvfs_module_context *ntvfs,
+                            struct ntvfs_request *req, union smb_ioctl *io)
+{
+       NTSTATUS status;
 
-       nbench_log(private, "Ioctl - NOT HANDLED\n");
+       PASS_THRU_REQ(ntvfs, req, ioctl, io, (ntvfs, req, io));
 
        return status;
 }
@@ -166,16 +202,24 @@ static NTSTATUS nbench_ioctl(struct smbsrv_request *req, union smb_ioctl *io)
 /*
   check if a directory exists
 */
-static NTSTATUS nbench_chkpath(struct smbsrv_request *req, struct smb_chkpath *cp)
+static void nbench_chkpath_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
+       union smb_chkpath *cp = req->async_states->private_data;
+
+       nbench_log(req, "Chkpath \"%s\" %s\n", 
+                  cp->chkpath.in.path, 
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
 
-       PASS_THRU_REQ(req, chkpath, (req, cp));
+static NTSTATUS nbench_chkpath(struct ntvfs_module_context *ntvfs,
+                              struct ntvfs_request *req,
+                              union smb_chkpath *cp)
+{
+       NTSTATUS status;
 
-       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;
 }
@@ -183,17 +227,24 @@ static NTSTATUS nbench_chkpath(struct smbsrv_request *req, struct smb_chkpath *c
 /*
   return info on a pathname
 */
-static NTSTATUS nbench_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *info)
+static void nbench_qpathinfo_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
+       union smb_fileinfo *info = req->async_states->private_data;
 
-       PASS_THRU_REQ(req, qpathinfo, (req, info));
-
-       nbench_log(private, "QUERY_PATH_INFORMATION \"%s\" %d %s\n", 
-                  info->generic.in.fname, 
+       nbench_log(req, "QUERY_PATH_INFORMATION \"%s\" %d %s\n", 
+                  info->generic.in.file.path, 
                   info->generic.level,
-                  get_nt_error_c_code(status));
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_qpathinfo(struct ntvfs_module_context *ntvfs,
+                                struct ntvfs_request *req, union smb_fileinfo *info)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, qpathinfo, info, (ntvfs, req, info));
 
        return status;
 }
@@ -201,36 +252,49 @@ static NTSTATUS nbench_qpathinfo(struct smbsrv_request *req, union smb_fileinfo
 /*
   query info on a open file
 */
-static NTSTATUS nbench_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *info)
+static void nbench_qfileinfo_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
-
-       PASS_THRU_REQ(req, qfileinfo, (req, info));
+       union smb_fileinfo *info = req->async_states->private_data;
 
-       nbench_log(private, "QUERY_FILE_INFORMATION %d %d %s\n", 
-                  info->generic.in.fnum, 
+       nbench_log(req, "QUERY_FILE_INFORMATION %s %d %s\n", 
+                  nbench_ntvfs_handle_string(req, info->generic.in.file.ntvfs),
                   info->generic.level,
-                  get_nt_error_c_code(status));
+                  get_nt_error_c_code(req->async_states->status));
 
-       return status;
+       PASS_THRU_REP_POST(req);
 }
 
+static NTSTATUS nbench_qfileinfo(struct ntvfs_module_context *ntvfs,
+                                struct ntvfs_request *req, union smb_fileinfo *info)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, qfileinfo, info, (ntvfs, req, info));
+
+       return status;
+}
 
 /*
   set info on a pathname
 */
-static NTSTATUS nbench_setpathinfo(struct smbsrv_request *req, union smb_setfileinfo *st)
+static void nbench_setpathinfo_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
+       union smb_setfileinfo *st = req->async_states->private_data;
 
-       PASS_THRU_REQ(req, setpathinfo, (req, st));
-
-       nbench_log(private, "SET_PATH_INFORMATION \"%s\" %d %s\n", 
-                  st->generic.file.fname, 
+       nbench_log(req, "SET_PATH_INFORMATION \"%s\" %d %s\n", 
+                  st->generic.in.file.path, 
                   st->generic.level,
-                  get_nt_error_c_code(status));
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_setpathinfo(struct ntvfs_module_context *ntvfs,
+                                  struct ntvfs_request *req, union smb_setfileinfo *st)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, setpathinfo, st, (ntvfs, req, st));
 
        return status;
 }
@@ -238,43 +302,59 @@ static NTSTATUS nbench_setpathinfo(struct smbsrv_request *req, union smb_setfile
 /*
   open a file
 */
-static NTSTATUS nbench_open(struct smbsrv_request *req, union smb_open *io)
+static void nbench_open_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
-
-       PASS_THRU_REQ(req, open, (req, io));
+       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", 
+               if (!NT_STATUS_IS_OK(req->async_states->status)) {
+                       ZERO_STRUCT(io->ntcreatex.out);
+               }
+               nbench_log(req, "NTCreateX \"%s\" 0x%x 0x%x %s %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));
+                          nbench_ntvfs_handle_string(req, io->ntcreatex.out.file.ntvfs),
+                          get_nt_error_c_code(req->async_states->status));
                break;
 
        default:
-               nbench_log(private, "Open-%d - NOT HANDLED\n",
+               nbench_log(req, "Open-%d - NOT HANDLED\n",
                           io->generic.level);
                break;
        }
 
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_open(struct ntvfs_module_context *ntvfs,
+                           struct ntvfs_request *req, union smb_open *io)
+{
+       NTSTATUS status;
+
+#undef open /* AIX defines open to be open64 */
+       PASS_THRU_REQ(ntvfs, req, open, io, (ntvfs, req, io));
+
        return status;
 }
 
 /*
   create a directory
 */
-static NTSTATUS nbench_mkdir(struct smbsrv_request *req, union smb_mkdir *md)
+static void nbench_mkdir_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
+       nbench_log(req, "Mkdir - NOT HANDLED\n");
 
-       PASS_THRU_REQ(req, mkdir, (req, md));
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_mkdir(struct ntvfs_module_context *ntvfs,
+                            struct ntvfs_request *req, union smb_mkdir *md)
+{
+       NTSTATUS status;
 
-       nbench_log(private, "Mkdir - NOT HANDLED\n");
+       PASS_THRU_REQ(ntvfs, req, mkdir, md, (ntvfs, req, md));
 
        return status;
 }
@@ -282,16 +362,23 @@ static NTSTATUS nbench_mkdir(struct smbsrv_request *req, union smb_mkdir *md)
 /*
   remove a directory
 */
-static NTSTATUS nbench_rmdir(struct smbsrv_request *req, struct smb_rmdir *rd)
+static void nbench_rmdir_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
-
-       PASS_THRU_REQ(req, rmdir, (req, rd));
+       struct smb_rmdir *rd = req->async_states->private_data;
 
-       nbench_log(private, "Rmdir \"%s\" %s\n", 
+       nbench_log(req, "Rmdir \"%s\" %s\n", 
                   rd->in.path, 
-                  get_nt_error_c_code(status));
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_rmdir(struct ntvfs_module_context *ntvfs,
+                            struct ntvfs_request *req, struct smb_rmdir *rd)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, rmdir, rd, (ntvfs, req, rd));
 
        return status;
 }
@@ -299,41 +386,53 @@ static NTSTATUS nbench_rmdir(struct smbsrv_request *req, struct smb_rmdir *rd)
 /*
   rename a set of files
 */
-static NTSTATUS nbench_rename(struct smbsrv_request *req, union smb_rename *ren)
+static void nbench_rename_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
-
-       PASS_THRU_REQ(req, rename, (req, ren));
+       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(req, "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(req, "Rename-%d - NOT HANDLED\n",
                           ren->generic.level);
                break;
        }
 
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_rename(struct ntvfs_module_context *ntvfs,
+                             struct ntvfs_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 NTSTATUS nbench_copy(struct smbsrv_request *req, struct smb_copy *cp)
+static void nbench_copy_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
+       nbench_log(req, "Copy - NOT HANDLED\n");
+
+       PASS_THRU_REP_POST(req);
+}
 
-       PASS_THRU_REQ(req, copy, (req, cp));
+static NTSTATUS nbench_copy(struct ntvfs_module_context *ntvfs,
+                           struct ntvfs_request *req, struct smb_copy *cp)
+{
+       NTSTATUS status;
 
-       nbench_log(private, "Copy - NOT HANDLED\n");
+       PASS_THRU_REQ(ntvfs, req, copy, cp, (ntvfs, req, cp));
 
        return status;
 }
@@ -341,80 +440,109 @@ static NTSTATUS nbench_copy(struct smbsrv_request *req, struct smb_copy *cp)
 /*
   read from a file
 */
-static NTSTATUS nbench_read(struct smbsrv_request *req, union smb_read *rd)
+static void nbench_read_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
-
-       PASS_THRU_REQ(req, read, (req, rd));
-
+       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", 
-                          rd->readx.in.fnum, 
+               if (!NT_STATUS_IS_OK(req->async_states->status)) {
+                       ZERO_STRUCT(rd->readx.out);
+               }
+               nbench_log(req, "ReadX %s %d %d %d %s\n", 
+                          nbench_ntvfs_handle_string(req, rd->readx.in.file.ntvfs),
                           (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(req, "Read-%d - NOT HANDLED\n",
                           rd->generic.level);
                break;
        }
 
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_read(struct ntvfs_module_context *ntvfs,
+                           struct ntvfs_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 smbsrv_request *req, union smb_write *wr)
+static void nbench_write_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
-
-       PASS_THRU_REQ(req, write, (req, wr));
+       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", 
-                          wr->writex.in.fnum, 
+               if (!NT_STATUS_IS_OK(req->async_states->status)) {
+                       ZERO_STRUCT(wr->writex.out);
+               }
+               nbench_log(req, "WriteX %s %d %d %d %s\n", 
+                          nbench_ntvfs_handle_string(req, wr->writex.in.file.ntvfs),
                           (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", 
-                          wr->write.in.fnum, 
+               if (!NT_STATUS_IS_OK(req->async_states->status)) {
+                       ZERO_STRUCT(wr->write.out);
+               }
+               nbench_log(req, "Write %s %d %d %d %s\n", 
+                          nbench_ntvfs_handle_string(req, wr->write.in.file.ntvfs),
                           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(req, "Write-%d - NOT HANDLED\n",
                           wr->generic.level);
                break;
        }
 
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_write(struct ntvfs_module_context *ntvfs,
+                            struct ntvfs_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 NTSTATUS nbench_seek(struct smbsrv_request *req, struct smb_seek *io)
+static void nbench_seek_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
+       nbench_log(req, "Seek - NOT HANDLED\n");
 
-       PASS_THRU_REQ(req, seek, (req, io));
+       PASS_THRU_REP_POST(req);
+}
 
-       nbench_log(private, "Seek - NOT HANDLED\n");
+static NTSTATUS nbench_seek(struct ntvfs_module_context *ntvfs,
+                           struct ntvfs_request *req,
+                           union smb_seek *io)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, seek, io, (ntvfs, req, io));
 
        return status;
 }
@@ -422,16 +550,37 @@ static NTSTATUS nbench_seek(struct smbsrv_request *req, struct smb_seek *io)
 /*
   flush a file
 */
-static NTSTATUS nbench_flush(struct smbsrv_request *req, struct smb_flush *io)
+static void nbench_flush_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
+       union smb_flush *io = req->async_states->private_data;
 
-       PASS_THRU_REQ(req, flush, (req, io));
+       switch (io->generic.level) {
+       case RAW_FLUSH_FLUSH:
+               nbench_log(req, "Flush %s %s\n",
+                          nbench_ntvfs_handle_string(req, io->flush.in.file.ntvfs),
+                          get_nt_error_c_code(req->async_states->status));
+               break;
+       case RAW_FLUSH_ALL:
+               nbench_log(req, "Flush %d %s\n",
+                          0xFFFF,
+                          get_nt_error_c_code(req->async_states->status));
+               break;
+       default:
+               nbench_log(req, "Flush-%d - NOT HANDLED\n",
+                          io->generic.level);
+               break;
+       }
 
-       nbench_log(private, "Flush %d %s\n",
-                  io->in.fnum,
-                  get_nt_error_c_code(status));
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_flush(struct ntvfs_module_context *ntvfs,
+                            struct ntvfs_request *req,
+                            union smb_flush *io)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, flush, io, (ntvfs, req, io));
 
        return status;
 }
@@ -439,107 +588,202 @@ static NTSTATUS nbench_flush(struct smbsrv_request *req, struct smb_flush *io)
 /*
   close a file
 */
-static NTSTATUS nbench_close(struct smbsrv_request *req, union smb_close *io)
+static void nbench_close_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
-
-       PASS_THRU_REQ(req, close, (req, io));
+       union smb_close *io = req->async_states->private_data;
 
        switch (io->generic.level) {
        case RAW_CLOSE_CLOSE:
-               nbench_log(private, "Close %d %s\n",
-                          io->close.in.fnum,
-                          get_nt_error_c_code(status));
+               nbench_log(req, "Close %s %s\n",
+                          nbench_ntvfs_handle_string(req, io->close.in.file.ntvfs),
+                          get_nt_error_c_code(req->async_states->status));
                break;
 
        default:
-               nbench_log(private, "Close-%d - NOT HANDLED\n",
+               nbench_log(req, "Close-%d - NOT HANDLED\n",
                           io->generic.level);
                break;
        }               
 
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_close(struct ntvfs_module_context *ntvfs,
+                            struct ntvfs_request *req, union smb_close *io)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, close, io, (ntvfs, req, io));
+
        return status;
 }
 
 /*
   exit - closing files
 */
-static NTSTATUS nbench_exit(struct smbsrv_request *req)
+static void nbench_exit_send(struct ntvfs_request *req)
+{
+       nbench_log(req, "Exit - NOT HANDLED\n");
+
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_exit(struct ntvfs_module_context *ntvfs,
+                           struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
        NTSTATUS status;
 
-       PASS_THRU_REQ(req, exit, (req));
+       PASS_THRU_REQ(ntvfs, req, exit, NULL, (ntvfs, req));
 
        return status;
 }
 
 /*
-  lock a byte range
+  logoff - closing files
+*/
+static void nbench_logoff_send(struct ntvfs_request *req)
+{
+       nbench_log(req, "Logoff - NOT HANDLED\n");
+
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_logoff(struct ntvfs_module_context *ntvfs,
+                             struct ntvfs_request *req)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, logoff, NULL, (ntvfs, req));
+
+       return status;
+}
+
+/*
+  async_setup - send fn
+*/
+static void nbench_async_setup_send(struct ntvfs_request *req)
+{
+       PASS_THRU_REP_POST(req);
+}
+
+/*
+  async setup
+*/
+static NTSTATUS nbench_async_setup(struct ntvfs_module_context *ntvfs,
+                                  struct ntvfs_request *req,
+                                  void *private)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, async_setup, NULL, (ntvfs, req, private));
+
+       return status;
+}
+
+
+static void nbench_cancel_send(struct ntvfs_request *req)
+{
+       PASS_THRU_REP_POST(req);
+}
+
+/*
+  cancel an existing async request
 */
-static NTSTATUS nbench_lock(struct smbsrv_request *req, union smb_lock *lck)
+static NTSTATUS nbench_cancel(struct ntvfs_module_context *ntvfs,
+                             struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
        NTSTATUS status;
 
-       PASS_THRU_REQ(req, lock, (req, lck));
+       PASS_THRU_REQ(ntvfs, req, cancel, NULL, (ntvfs, req));
+
+       return status;
+}
+
+/*
+  lock a byte range
+*/
+static void nbench_lock_send(struct ntvfs_request *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", 
-                          lck->lockx.in.fnum,
+               nbench_log(req, "LockX %s %d %d %s\n", 
+                          nbench_ntvfs_handle_string(req, lck->lockx.in.file.ntvfs),
                           (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", 
-                          lck->lockx.in.fnum,
+               nbench_log(req, "UnlockX %s %d %d %s\n", 
+                          nbench_ntvfs_handle_string(req, lck->lockx.in.file.ntvfs),
                           (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(req, "Lock-%d - NOT HANDLED\n", lck->generic.level);
        }
 
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_lock(struct ntvfs_module_context *ntvfs,
+                           struct ntvfs_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 NTSTATUS nbench_setfileinfo(struct smbsrv_request *req, 
-                                union smb_setfileinfo *info)
+static void nbench_setfileinfo_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
-
-       PASS_THRU_REQ(req, setfileinfo, (req, info));
+       union smb_setfileinfo *info = req->async_states->private_data;
 
-       nbench_log(private, "SET_FILE_INFORMATION %d %d %s\n", 
-                  info->generic.file.fnum,
+       nbench_log(req, "SET_FILE_INFORMATION %s %d %s\n", 
+                  nbench_ntvfs_handle_string(req, info->generic.in.file.ntvfs),
                   info->generic.level,
-                  get_nt_error_c_code(status));
+                  get_nt_error_c_code(req->async_states->status));
 
-       return status;
+       PASS_THRU_REP_POST(req);
 }
 
+static NTSTATUS nbench_setfileinfo(struct ntvfs_module_context *ntvfs,
+                                  struct ntvfs_request *req, 
+                                  union smb_setfileinfo *info)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, setfileinfo, info, (ntvfs, req, info));
+
+       return status;
+}
 
 /*
   return filesystem space info
 */
-static NTSTATUS nbench_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs)
+static void nbench_fsinfo_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
-
-       PASS_THRU_REQ(req, fsinfo, (req, fs));
+       union smb_fsinfo *fs = req->async_states->private_data;
 
-       nbench_log(private, "QUERY_FS_INFORMATION %d %s\n", 
+       nbench_log(req, "QUERY_FS_INFORMATION %d %s\n", 
                   fs->generic.level, 
-                  get_nt_error_c_code(status));
+                  get_nt_error_c_code(req->async_states->status));
+
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_fsinfo(struct ntvfs_module_context *ntvfs,
+                             struct ntvfs_request *req, union smb_fsinfo *fs)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, fsinfo, fs, (ntvfs, req, fs));
 
        return status;
 }
@@ -547,14 +791,21 @@ static NTSTATUS nbench_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs)
 /*
   return print queue info
 */
-static NTSTATUS nbench_lpq(struct smbsrv_request *req, union smb_lpq *lpq)
+static void nbench_lpq_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
+       union smb_lpq *lpq = req->async_states->private_data;
+
+       nbench_log(req, "Lpq-%d - NOT HANDLED\n", lpq->generic.level);
+
+       PASS_THRU_REP_POST(req);
+}
 
-       PASS_THRU_REQ(req, lpq, (req, lpq));
+static NTSTATUS nbench_lpq(struct ntvfs_module_context *ntvfs,
+                          struct ntvfs_request *req, union smb_lpq *lpq)
+{
+       NTSTATUS status;
 
-       nbench_log(private, "Lpq-%d - NOT HANDLED\n", lpq->generic.level);
+       PASS_THRU_REQ(ntvfs, req, lpq, lpq, (ntvfs, req, lpq));
 
        return status;
 }
@@ -562,70 +813,99 @@ static NTSTATUS nbench_lpq(struct smbsrv_request *req, union smb_lpq *lpq)
 /* 
    list files in a directory matching a wildcard pattern
 */
-static NTSTATUS nbench_search_first(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 ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
-
-       PASS_THRU_REQ(req, search_first, (req, io, search_private, callback));
-
+       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", 
+       case RAW_SEARCH_TRANS2:
+               if (NT_STATUS_IS_ERR(req->async_states->status)) {
+                       ZERO_STRUCT(io->t2ffirst.out);
+               }
+               nbench_log(req, "FIND_FIRST \"%s\" %d %d %d %s\n", 
                           io->t2ffirst.in.pattern,
-                          io->generic.level,
+                          io->t2ffirst.data_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(req, "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 ntvfs_request *req, union smb_search_first *io, 
+                                   void *search_private, 
+                                   BOOL (*callback)(void *, const 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 NTSTATUS nbench_search_next(struct smbsrv_request *req, union smb_search_next *io, 
-                                void *search_private, 
-                                BOOL (*callback)(void *, union smb_search_data *))
+static void nbench_search_next_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
+       union smb_search_next *io = req->async_states->private_data;
+
+       nbench_log(req, "Searchnext-%d - NOT HANDLED\n", io->generic.level);
 
-       PASS_THRU_REQ(req, search_next, (req, io, search_private, callback));
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_search_next(struct ntvfs_module_context *ntvfs,
+                                  struct ntvfs_request *req, union smb_search_next *io, 
+                                  void *search_private, 
+                                  BOOL (*callback)(void *, const union smb_search_data *))
+{
+       NTSTATUS status;
 
-       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 NTSTATUS nbench_search_close(struct smbsrv_request *req, union smb_search_close *io)
+static void nbench_search_close_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
+       union smb_search_close *io = req->async_states->private_data;
 
-       PASS_THRU_REQ(req, search_close, (req, io));
+       nbench_log(req, "Searchclose-%d - NOT HANDLED\n", io->generic.level);
 
-       nbench_log(private, "Searchclose-%d - NOT HANDLED\n", io->generic.level);
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_search_close(struct ntvfs_module_context *ntvfs,
+                                   struct ntvfs_request *req, union smb_search_close *io)
+{
+       NTSTATUS status;
+
+       PASS_THRU_REQ(ntvfs, req, search_close, io, (ntvfs, req, io));
 
        return status;
 }
 
 /* SMBtrans - not used on file shares */
-static NTSTATUS nbench_trans(struct smbsrv_request *req, struct smb_trans2 *trans2)
+static void nbench_trans_send(struct ntvfs_request *req)
 {
-       NTVFS_GET_PRIVATE(nbench_private, private, req);
-       NTSTATUS status;
+       nbench_log(req, "Trans - NOT HANDLED\n");
 
-       PASS_THRU_REQ(req, trans, (req,trans2));
+       PASS_THRU_REP_POST(req);
+}
+
+static NTSTATUS nbench_trans(struct ntvfs_module_context *ntvfs,
+                            struct ntvfs_request *req, struct smb_trans2 *trans2)
+{
+       NTSTATUS status;
 
-       nbench_log(private, "Trans - NOT HANDLED\n");
+       PASS_THRU_REQ(ntvfs, req, trans, trans2, (ntvfs, req, trans2));
 
        return status;
 }
@@ -637,6 +917,7 @@ NTSTATUS ntvfs_nbench_init(void)
 {
        NTSTATUS ret;
        struct ntvfs_ops ops;
+       NTVFS_CURRENT_CRITICAL_SIZES(vers);
 
        ZERO_STRUCT(ops);
 
@@ -672,13 +953,16 @@ NTSTATUS ntvfs_nbench_init(void)
        ops.search_next = nbench_search_next;
        ops.search_close = nbench_search_close;
        ops.trans = nbench_trans;
+       ops.logoff = nbench_logoff;
+       ops.async_setup = nbench_async_setup;
+       ops.cancel = nbench_cancel;
 
        /* we don't register a trans2 handler as we want to be able to
           log individual trans2 requests */
        ops.trans2 = NULL;
 
        /* register ourselves with the NTVFS subsystem. */
-       ret = register_backend("ntvfs", &ops);
+       ret = ntvfs_register(&ops, &vers);
 
        if (!NT_STATUS_IS_OK(ret)) {
                DEBUG(0,("Failed to register nbench backend!\n"));