2 Unix SMB/CIFS implementation.
4 a pass-thru NTVFS module to record a NBENCH load file
6 Copyright (C) Andrew Tridgell 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 "passthru" in this module refers to the next level of NTVFS being used
27 #include "ntvfs/ntvfs.h"
28 #include "system/filesys.h"
30 NTSTATUS ntvfs_nbench_init(void);
32 /* this is stored in ntvfs_private */
33 struct nbench_private {
38 log one request to the nbench log
40 static void nbench_log(struct ntvfs_request *req,
41 const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
43 static void nbench_log(struct ntvfs_request *req,
44 const char *format, ...)
46 struct nbench_private *nprivates = req->async_states->ntvfs->private_data;
52 ret = vasprintf(&s, format, ap);
59 write(nprivates->log_fd, s, strlen(s));
63 static char *nbench_ntvfs_handle_string(struct ntvfs_request *req, struct ntvfs_handle *h)
68 key = ntvfs_handle_get_wire_key(h, req);
71 case 2: /* SMB fnum */
72 fnum = SVAL(key.data, 0);
75 DEBUG(0,("%s: invalid wire handle size: %u\n",
76 __FUNCTION__, (unsigned)key.length));
80 return talloc_asprintf(req, "%u", fnum);
84 this pass through macro operates on request contexts, and disables
87 async calls are a pain for the nbench module as it makes pulling the
88 status code and any result parameters much harder.
90 #define PASS_THRU_REQ_PRE_ASYNC(ntvfs, req, op, par1) do { \
91 status = ntvfs_async_state_push(ntvfs, req, par1, nbench_##op##_send); \
92 if (!NT_STATUS_IS_OK(status)) { \
97 #define PASS_THRU_REQ_POST_ASYNC(req) do { \
98 req->async_states->status = status; \
99 if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
100 req->async_states->send_fn(req); \
104 #define PASS_THRU_REQ(ntvfs, req, op, par1, args) do { \
105 PASS_THRU_REQ_PRE_ASYNC(ntvfs, req, op, par1); \
106 status = ntvfs_next_##op args; \
107 PASS_THRU_REQ_POST_ASYNC(req); \
110 #define PASS_THRU_REP_POST(req) do { \
111 ntvfs_async_state_pop(req); \
112 if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) { \
113 req->async_states->send_fn(req); \
118 connect to a share - used when a tree_connect operation comes in.
120 static NTSTATUS nbench_connect(struct ntvfs_module_context *ntvfs,
121 struct ntvfs_request *req,
124 struct nbench_private *nprivates;
126 char *logname = NULL;
128 nprivates = talloc(ntvfs, struct nbench_private);
130 return NT_STATUS_NO_MEMORY;
133 logname = talloc_asprintf(req, "/tmp/nbenchlog%d.%u", ntvfs->depth,
134 (unsigned int)getpid());
135 NT_STATUS_HAVE_NO_MEMORY(logname);
136 nprivates->log_fd = open(logname, O_WRONLY|O_CREAT|O_APPEND, 0644);
137 talloc_free(logname);
139 if (nprivates->log_fd == -1) {
140 DEBUG(0,("Failed to open nbench log\n"));
141 return NT_STATUS_UNSUCCESSFUL;
144 ntvfs->private_data = nprivates;
146 status = ntvfs_next_connect(ntvfs, req, con);
152 disconnect from a share
154 static NTSTATUS nbench_disconnect(struct ntvfs_module_context *ntvfs)
156 struct nbench_private *nprivates = ntvfs->private_data;
159 close(nprivates->log_fd);
161 status = ntvfs_next_disconnect(ntvfs);
167 delete a file - the dirtype specifies the file types to include in the search.
168 The name can contain CIFS wildcards, but rarely does (except with OS/2 clients)
170 static void nbench_unlink_send(struct ntvfs_request *req)
172 union smb_unlink *unl = req->async_states->private_data;
173 nbench_log(req, "Unlink \"%s\" 0x%x %s\n",
174 unl->unlink.in.pattern, unl->unlink.in.attrib,
175 get_nt_error_c_code(req, req->async_states->status));
177 PASS_THRU_REP_POST(req);
180 static NTSTATUS nbench_unlink(struct ntvfs_module_context *ntvfs,
181 struct ntvfs_request *req,
182 union smb_unlink *unl)
186 PASS_THRU_REQ(ntvfs, req, unlink, unl, (ntvfs, req, unl));
194 static void nbench_ioctl_send(struct ntvfs_request *req)
196 nbench_log(req, "Ioctl - NOT HANDLED\n");
198 PASS_THRU_REP_POST(req);
201 static NTSTATUS nbench_ioctl(struct ntvfs_module_context *ntvfs,
202 struct ntvfs_request *req, union smb_ioctl *io)
206 PASS_THRU_REQ(ntvfs, req, ioctl, io, (ntvfs, req, io));
212 check if a directory exists
214 static void nbench_chkpath_send(struct ntvfs_request *req)
216 union smb_chkpath *cp = req->async_states->private_data;
218 nbench_log(req, "Chkpath \"%s\" %s\n",
220 get_nt_error_c_code(req, req->async_states->status));
222 PASS_THRU_REP_POST(req);
225 static NTSTATUS nbench_chkpath(struct ntvfs_module_context *ntvfs,
226 struct ntvfs_request *req,
227 union smb_chkpath *cp)
231 PASS_THRU_REQ(ntvfs, req, chkpath, cp, (ntvfs, req, cp));
237 return info on a pathname
239 static void nbench_qpathinfo_send(struct ntvfs_request *req)
241 union smb_fileinfo *info = req->async_states->private_data;
243 nbench_log(req, "QUERY_PATH_INFORMATION \"%s\" %d %s\n",
244 info->generic.in.file.path,
246 get_nt_error_c_code(req, req->async_states->status));
248 PASS_THRU_REP_POST(req);
251 static NTSTATUS nbench_qpathinfo(struct ntvfs_module_context *ntvfs,
252 struct ntvfs_request *req, union smb_fileinfo *info)
256 PASS_THRU_REQ(ntvfs, req, qpathinfo, info, (ntvfs, req, info));
262 query info on a open file
264 static void nbench_qfileinfo_send(struct ntvfs_request *req)
266 union smb_fileinfo *info = req->async_states->private_data;
268 nbench_log(req, "QUERY_FILE_INFORMATION %s %d %s\n",
269 nbench_ntvfs_handle_string(req, info->generic.in.file.ntvfs),
271 get_nt_error_c_code(req, req->async_states->status));
273 PASS_THRU_REP_POST(req);
276 static NTSTATUS nbench_qfileinfo(struct ntvfs_module_context *ntvfs,
277 struct ntvfs_request *req, union smb_fileinfo *info)
281 PASS_THRU_REQ(ntvfs, req, qfileinfo, info, (ntvfs, req, info));
287 set info on a pathname
289 static void nbench_setpathinfo_send(struct ntvfs_request *req)
291 union smb_setfileinfo *st = req->async_states->private_data;
293 nbench_log(req, "SET_PATH_INFORMATION \"%s\" %d %s\n",
294 st->generic.in.file.path,
296 get_nt_error_c_code(req, req->async_states->status));
298 PASS_THRU_REP_POST(req);
301 static NTSTATUS nbench_setpathinfo(struct ntvfs_module_context *ntvfs,
302 struct ntvfs_request *req, union smb_setfileinfo *st)
306 PASS_THRU_REQ(ntvfs, req, setpathinfo, st, (ntvfs, req, st));
314 static void nbench_open_send(struct ntvfs_request *req)
316 union smb_open *io = req->async_states->private_data;
318 switch (io->generic.level) {
319 case RAW_OPEN_NTCREATEX:
320 if (!NT_STATUS_IS_OK(req->async_states->status)) {
321 ZERO_STRUCT(io->ntcreatex.out);
323 nbench_log(req, "NTCreateX \"%s\" 0x%x 0x%x %s %s\n",
324 io->ntcreatex.in.fname,
325 io->ntcreatex.in.create_options,
326 io->ntcreatex.in.open_disposition,
327 nbench_ntvfs_handle_string(req, io->ntcreatex.out.file.ntvfs),
328 get_nt_error_c_code(req, req->async_states->status));
332 nbench_log(req, "Open-%d - NOT HANDLED\n",
337 PASS_THRU_REP_POST(req);
340 static NTSTATUS nbench_open(struct ntvfs_module_context *ntvfs,
341 struct ntvfs_request *req, union smb_open *io)
345 #undef open /* AIX defines open to be open64 */
346 PASS_THRU_REQ(ntvfs, req, open, io, (ntvfs, req, io));
354 static void nbench_mkdir_send(struct ntvfs_request *req)
356 nbench_log(req, "Mkdir - NOT HANDLED\n");
358 PASS_THRU_REP_POST(req);
361 static NTSTATUS nbench_mkdir(struct ntvfs_module_context *ntvfs,
362 struct ntvfs_request *req, union smb_mkdir *md)
366 PASS_THRU_REQ(ntvfs, req, mkdir, md, (ntvfs, req, md));
374 static void nbench_rmdir_send(struct ntvfs_request *req)
376 struct smb_rmdir *rd = req->async_states->private_data;
378 nbench_log(req, "Rmdir \"%s\" %s\n",
380 get_nt_error_c_code(req, req->async_states->status));
382 PASS_THRU_REP_POST(req);
385 static NTSTATUS nbench_rmdir(struct ntvfs_module_context *ntvfs,
386 struct ntvfs_request *req, struct smb_rmdir *rd)
390 PASS_THRU_REQ(ntvfs, req, rmdir, rd, (ntvfs, req, rd));
396 rename a set of files
398 static void nbench_rename_send(struct ntvfs_request *req)
400 union smb_rename *ren = req->async_states->private_data;
402 switch (ren->generic.level) {
403 case RAW_RENAME_RENAME:
404 nbench_log(req, "Rename \"%s\" \"%s\" %s\n",
405 ren->rename.in.pattern1,
406 ren->rename.in.pattern2,
407 get_nt_error_c_code(req, req->async_states->status));
411 nbench_log(req, "Rename-%d - NOT HANDLED\n",
416 PASS_THRU_REP_POST(req);
419 static NTSTATUS nbench_rename(struct ntvfs_module_context *ntvfs,
420 struct ntvfs_request *req, union smb_rename *ren)
424 PASS_THRU_REQ(ntvfs, req, rename, ren, (ntvfs, req, ren));
432 static void nbench_copy_send(struct ntvfs_request *req)
434 nbench_log(req, "Copy - NOT HANDLED\n");
436 PASS_THRU_REP_POST(req);
439 static NTSTATUS nbench_copy(struct ntvfs_module_context *ntvfs,
440 struct ntvfs_request *req, struct smb_copy *cp)
444 PASS_THRU_REQ(ntvfs, req, copy, cp, (ntvfs, req, cp));
452 static void nbench_read_send(struct ntvfs_request *req)
454 union smb_read *rd = req->async_states->private_data;
456 switch (rd->generic.level) {
458 if (!NT_STATUS_IS_OK(req->async_states->status)) {
459 ZERO_STRUCT(rd->readx.out);
461 nbench_log(req, "ReadX %s %d %d %d %s\n",
462 nbench_ntvfs_handle_string(req, rd->readx.in.file.ntvfs),
463 (int)rd->readx.in.offset,
466 get_nt_error_c_code(req, req->async_states->status));
469 nbench_log(req, "Read-%d - NOT HANDLED\n",
474 PASS_THRU_REP_POST(req);
477 static NTSTATUS nbench_read(struct ntvfs_module_context *ntvfs,
478 struct ntvfs_request *req, union smb_read *rd)
482 PASS_THRU_REQ(ntvfs, req, read, rd, (ntvfs, req, rd));
490 static void nbench_write_send(struct ntvfs_request *req)
492 union smb_write *wr = req->async_states->private_data;
494 switch (wr->generic.level) {
495 case RAW_WRITE_WRITEX:
496 if (!NT_STATUS_IS_OK(req->async_states->status)) {
497 ZERO_STRUCT(wr->writex.out);
499 nbench_log(req, "WriteX %s %d %d %d %s\n",
500 nbench_ntvfs_handle_string(req, wr->writex.in.file.ntvfs),
501 (int)wr->writex.in.offset,
503 wr->writex.out.nwritten,
504 get_nt_error_c_code(req, req->async_states->status));
507 case RAW_WRITE_WRITE:
508 if (!NT_STATUS_IS_OK(req->async_states->status)) {
509 ZERO_STRUCT(wr->write.out);
511 nbench_log(req, "Write %s %d %d %d %s\n",
512 nbench_ntvfs_handle_string(req, wr->write.in.file.ntvfs),
515 wr->write.out.nwritten,
516 get_nt_error_c_code(req, req->async_states->status));
520 nbench_log(req, "Write-%d - NOT HANDLED\n",
525 PASS_THRU_REP_POST(req);
528 static NTSTATUS nbench_write(struct ntvfs_module_context *ntvfs,
529 struct ntvfs_request *req, union smb_write *wr)
533 PASS_THRU_REQ(ntvfs, req, write, wr, (ntvfs, req, wr));
541 static void nbench_seek_send(struct ntvfs_request *req)
543 nbench_log(req, "Seek - NOT HANDLED\n");
545 PASS_THRU_REP_POST(req);
548 static NTSTATUS nbench_seek(struct ntvfs_module_context *ntvfs,
549 struct ntvfs_request *req,
554 PASS_THRU_REQ(ntvfs, req, seek, io, (ntvfs, req, io));
562 static void nbench_flush_send(struct ntvfs_request *req)
564 union smb_flush *io = req->async_states->private_data;
566 switch (io->generic.level) {
567 case RAW_FLUSH_FLUSH:
568 nbench_log(req, "Flush %s %s\n",
569 nbench_ntvfs_handle_string(req, io->flush.in.file.ntvfs),
570 get_nt_error_c_code(req, req->async_states->status));
573 nbench_log(req, "Flush %d %s\n",
575 get_nt_error_c_code(req, req->async_states->status));
578 nbench_log(req, "Flush-%d - NOT HANDLED\n",
583 PASS_THRU_REP_POST(req);
586 static NTSTATUS nbench_flush(struct ntvfs_module_context *ntvfs,
587 struct ntvfs_request *req,
592 PASS_THRU_REQ(ntvfs, req, flush, io, (ntvfs, req, io));
600 static void nbench_close_send(struct ntvfs_request *req)
602 union smb_close *io = req->async_states->private_data;
604 switch (io->generic.level) {
605 case RAW_CLOSE_CLOSE:
606 nbench_log(req, "Close %s %s\n",
607 nbench_ntvfs_handle_string(req, io->close.in.file.ntvfs),
608 get_nt_error_c_code(req, req->async_states->status));
612 nbench_log(req, "Close-%d - NOT HANDLED\n",
617 PASS_THRU_REP_POST(req);
620 static NTSTATUS nbench_close(struct ntvfs_module_context *ntvfs,
621 struct ntvfs_request *req, union smb_close *io)
625 PASS_THRU_REQ(ntvfs, req, close, io, (ntvfs, req, io));
633 static void nbench_exit_send(struct ntvfs_request *req)
635 nbench_log(req, "Exit - NOT HANDLED\n");
637 PASS_THRU_REP_POST(req);
640 static NTSTATUS nbench_exit(struct ntvfs_module_context *ntvfs,
641 struct ntvfs_request *req)
645 PASS_THRU_REQ(ntvfs, req, exit, NULL, (ntvfs, req));
651 logoff - closing files
653 static void nbench_logoff_send(struct ntvfs_request *req)
655 nbench_log(req, "Logoff - NOT HANDLED\n");
657 PASS_THRU_REP_POST(req);
660 static NTSTATUS nbench_logoff(struct ntvfs_module_context *ntvfs,
661 struct ntvfs_request *req)
665 PASS_THRU_REQ(ntvfs, req, logoff, NULL, (ntvfs, req));
671 async_setup - send fn
673 static void nbench_async_setup_send(struct ntvfs_request *req)
675 PASS_THRU_REP_POST(req);
681 static NTSTATUS nbench_async_setup(struct ntvfs_module_context *ntvfs,
682 struct ntvfs_request *req,
687 PASS_THRU_REQ(ntvfs, req, async_setup, NULL, (ntvfs, req, private_data));
693 static void nbench_cancel_send(struct ntvfs_request *req)
695 PASS_THRU_REP_POST(req);
699 cancel an existing async request
701 static NTSTATUS nbench_cancel(struct ntvfs_module_context *ntvfs,
702 struct ntvfs_request *req)
706 PASS_THRU_REQ(ntvfs, req, cancel, NULL, (ntvfs, req));
714 static void nbench_lock_send(struct ntvfs_request *req)
716 union smb_lock *lck = req->async_states->private_data;
718 if (lck->generic.level == RAW_LOCK_LOCKX &&
719 lck->lockx.in.lock_cnt == 1 &&
720 lck->lockx.in.ulock_cnt == 0) {
721 nbench_log(req, "LockX %s %d %d %s\n",
722 nbench_ntvfs_handle_string(req, lck->lockx.in.file.ntvfs),
723 (int)lck->lockx.in.locks[0].offset,
724 (int)lck->lockx.in.locks[0].count,
725 get_nt_error_c_code(req, req->async_states->status));
726 } else if (lck->generic.level == RAW_LOCK_LOCKX &&
727 lck->lockx.in.ulock_cnt == 1) {
728 nbench_log(req, "UnlockX %s %d %d %s\n",
729 nbench_ntvfs_handle_string(req, lck->lockx.in.file.ntvfs),
730 (int)lck->lockx.in.locks[0].offset,
731 (int)lck->lockx.in.locks[0].count,
732 get_nt_error_c_code(req, req->async_states->status));
734 nbench_log(req, "Lock-%d - NOT HANDLED\n", lck->generic.level);
737 PASS_THRU_REP_POST(req);
740 static NTSTATUS nbench_lock(struct ntvfs_module_context *ntvfs,
741 struct ntvfs_request *req, union smb_lock *lck)
745 PASS_THRU_REQ(ntvfs, req, lock, lck, (ntvfs, req, lck));
751 set info on a open file
753 static void nbench_setfileinfo_send(struct ntvfs_request *req)
755 union smb_setfileinfo *info = req->async_states->private_data;
757 nbench_log(req, "SET_FILE_INFORMATION %s %d %s\n",
758 nbench_ntvfs_handle_string(req, info->generic.in.file.ntvfs),
760 get_nt_error_c_code(req, req->async_states->status));
762 PASS_THRU_REP_POST(req);
765 static NTSTATUS nbench_setfileinfo(struct ntvfs_module_context *ntvfs,
766 struct ntvfs_request *req,
767 union smb_setfileinfo *info)
771 PASS_THRU_REQ(ntvfs, req, setfileinfo, info, (ntvfs, req, info));
777 return filesystem space info
779 static void nbench_fsinfo_send(struct ntvfs_request *req)
781 union smb_fsinfo *fs = req->async_states->private_data;
783 nbench_log(req, "QUERY_FS_INFORMATION %d %s\n",
785 get_nt_error_c_code(req, req->async_states->status));
787 PASS_THRU_REP_POST(req);
790 static NTSTATUS nbench_fsinfo(struct ntvfs_module_context *ntvfs,
791 struct ntvfs_request *req, union smb_fsinfo *fs)
795 PASS_THRU_REQ(ntvfs, req, fsinfo, fs, (ntvfs, req, fs));
801 return print queue info
803 static void nbench_lpq_send(struct ntvfs_request *req)
805 union smb_lpq *lpq = req->async_states->private_data;
807 nbench_log(req, "Lpq-%d - NOT HANDLED\n", lpq->generic.level);
809 PASS_THRU_REP_POST(req);
812 static NTSTATUS nbench_lpq(struct ntvfs_module_context *ntvfs,
813 struct ntvfs_request *req, union smb_lpq *lpq)
817 PASS_THRU_REQ(ntvfs, req, lpq, lpq, (ntvfs, req, lpq));
823 list files in a directory matching a wildcard pattern
825 static void nbench_search_first_send(struct ntvfs_request *req)
827 union smb_search_first *io = req->async_states->private_data;
829 switch (io->generic.level) {
830 case RAW_SEARCH_TRANS2:
831 if (NT_STATUS_IS_ERR(req->async_states->status)) {
832 ZERO_STRUCT(io->t2ffirst.out);
834 nbench_log(req, "FIND_FIRST \"%s\" %d %d %d %s\n",
835 io->t2ffirst.in.pattern,
836 io->t2ffirst.data_level,
837 io->t2ffirst.in.max_count,
838 io->t2ffirst.out.count,
839 get_nt_error_c_code(req, req->async_states->status));
843 nbench_log(req, "Search-%d - NOT HANDLED\n", io->generic.level);
847 PASS_THRU_REP_POST(req);
850 static NTSTATUS nbench_search_first(struct ntvfs_module_context *ntvfs,
851 struct ntvfs_request *req, union smb_search_first *io,
852 void *search_private,
853 bool (*callback)(void *, const union smb_search_data *))
857 PASS_THRU_REQ(ntvfs, req, search_first, io, (ntvfs, req, io, search_private, callback));
862 /* continue a search */
863 static void nbench_search_next_send(struct ntvfs_request *req)
865 union smb_search_next *io = req->async_states->private_data;
867 nbench_log(req, "Searchnext-%d - NOT HANDLED\n", io->generic.level);
869 PASS_THRU_REP_POST(req);
872 static NTSTATUS nbench_search_next(struct ntvfs_module_context *ntvfs,
873 struct ntvfs_request *req, union smb_search_next *io,
874 void *search_private,
875 bool (*callback)(void *, const union smb_search_data *))
879 PASS_THRU_REQ(ntvfs, req, search_next, io, (ntvfs, req, io, search_private, callback));
885 static void nbench_search_close_send(struct ntvfs_request *req)
887 union smb_search_close *io = req->async_states->private_data;
889 nbench_log(req, "Searchclose-%d - NOT HANDLED\n", io->generic.level);
891 PASS_THRU_REP_POST(req);
894 static NTSTATUS nbench_search_close(struct ntvfs_module_context *ntvfs,
895 struct ntvfs_request *req, union smb_search_close *io)
899 PASS_THRU_REQ(ntvfs, req, search_close, io, (ntvfs, req, io));
904 /* SMBtrans - not used on file shares */
905 static void nbench_trans_send(struct ntvfs_request *req)
907 nbench_log(req, "Trans - NOT HANDLED\n");
909 PASS_THRU_REP_POST(req);
912 static NTSTATUS nbench_trans(struct ntvfs_module_context *ntvfs,
913 struct ntvfs_request *req, struct smb_trans2 *trans2)
917 PASS_THRU_REQ(ntvfs, req, trans, trans2, (ntvfs, req, trans2));
923 initialise the nbench backend, registering ourselves with the ntvfs subsystem
925 NTSTATUS ntvfs_nbench_init(void)
928 struct ntvfs_ops ops;
929 NTVFS_CURRENT_CRITICAL_SIZES(vers);
933 /* fill in the name and type */
935 ops.type = NTVFS_DISK;
937 /* fill in all the operations */
938 ops.connect_fn = nbench_connect;
939 ops.disconnect_fn = nbench_disconnect;
940 ops.unlink_fn = nbench_unlink;
941 ops.chkpath_fn = nbench_chkpath;
942 ops.qpathinfo_fn = nbench_qpathinfo;
943 ops.setpathinfo_fn = nbench_setpathinfo;
944 ops.open_fn = nbench_open;
945 ops.mkdir_fn = nbench_mkdir;
946 ops.rmdir_fn = nbench_rmdir;
947 ops.rename_fn = nbench_rename;
948 ops.copy_fn = nbench_copy;
949 ops.ioctl_fn = nbench_ioctl;
950 ops.read_fn = nbench_read;
951 ops.write_fn = nbench_write;
952 ops.seek_fn = nbench_seek;
953 ops.flush_fn = nbench_flush;
954 ops.close_fn = nbench_close;
955 ops.exit_fn = nbench_exit;
956 ops.lock_fn = nbench_lock;
957 ops.setfileinfo_fn = nbench_setfileinfo;
958 ops.qfileinfo_fn = nbench_qfileinfo;
959 ops.fsinfo_fn = nbench_fsinfo;
960 ops.lpq_fn = nbench_lpq;
961 ops.search_first_fn = nbench_search_first;
962 ops.search_next_fn = nbench_search_next;
963 ops.search_close_fn = nbench_search_close;
964 ops.trans_fn = nbench_trans;
965 ops.logoff_fn = nbench_logoff;
966 ops.async_setup_fn = nbench_async_setup;
967 ops.cancel_fn = nbench_cancel;
969 /* we don't register a trans2 handler as we want to be able to
970 log individual trans2 requests */
971 ops.trans2_fn = NULL;
973 /* register ourselves with the NTVFS subsystem. */
974 ret = ntvfs_register(&ops, &vers);
976 if (!NT_STATUS_IS_OK(ret)) {
977 DEBUG(0,("Failed to register nbench backend!\n"));