r3461: another place where "open" was used as a structure element
[kai/samba-autobuild/.git] / source4 / ntvfs / nbench / vfs_nbench.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    a pass-thru NTVFS module to record a NBENCH load file
5
6    Copyright (C) Andrew Tridgell 2004
7
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 2 of the License, or
11    (at your option) any later version.
12    
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.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 /*
24   "passthru" in this module refers to the next level of NTVFS being used
25 */
26
27 #include "includes.h"
28
29 /* this is stored in ntvfs_private */
30 struct nbench_private {
31         int log_fd;
32 };
33
34 /*
35   log one request to the nbench log
36 */
37 static void nbench_log(struct smbsrv_request *req,
38                        const char *format, ...) PRINTF_ATTRIBUTE(2, 3);
39
40 static void nbench_log(struct smbsrv_request *req,
41                        const char *format, ...)
42 {
43         struct nbench_private *private = req->async_states->ntvfs->private_data;
44         va_list ap;
45         char *s = NULL;
46
47         va_start(ap, format);
48         vasprintf(&s, format, ap);
49         va_end(ap);
50
51         write(private->log_fd, s, strlen(s));
52         free(s);
53 }
54
55 /*
56   this pass through macro operates on request contexts, and disables
57   async calls. 
58
59   async calls are a pain for the nbench module as it makes pulling the
60   status code and any result parameters much harder.
61 */
62 #define PASS_THRU_REQ_PRE_ASYNC(ntvfs, req, op, par1) do { \
63         status = ntvfs_async_state_push(req, par1, nbench_##op##_send, ntvfs); \
64         if (!NT_STATUS_IS_OK(status)) { \
65                 return status; \
66         } \
67 } while (0)
68
69 #define PASS_THRU_REQ_POST_ASYNC(req) do { \
70         req->async_states->status = status; \
71         if (!(req->async_states->state & NTVFS_ASYNC_STATE_ASYNC)) { \
72                 req->async_states->send_fn(req); \
73         } \
74 } while (0)
75
76 #define PASS_THRU_REQ(ntvfs, req, op, par1, args) do { \
77         PASS_THRU_REQ_PRE_ASYNC(ntvfs, req, op, par1); \
78         status = ntvfs_next_##op args; \
79         PASS_THRU_REQ_POST_ASYNC(req); \
80 } while (0)
81
82 #define PASS_THRU_REP_POST(req) do { \
83         ntvfs_async_state_pop(req); \
84         if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) { \
85                 req->async_states->send_fn(req); \
86         } \
87 } while (0)
88
89 /*
90   connect to a share - used when a tree_connect operation comes in.
91 */
92 static NTSTATUS nbench_connect(struct ntvfs_module_context *ntvfs,
93                                struct smbsrv_request *req, const char *sharename)
94 {
95         struct nbench_private *nprivates;
96         NTSTATUS status;
97         char *logname = NULL;
98
99         nprivates = talloc_p(req->tcon, struct nbench_private);
100         if (!nprivates) {
101                 return NT_STATUS_NO_MEMORY;
102         }
103
104         asprintf(&logname, "/tmp/nbenchlog%d.%u", ntvfs->depth, getpid());
105         nprivates->log_fd = open(logname, O_WRONLY|O_CREAT|O_APPEND, 0644);
106         free(logname);
107
108         if (nprivates->log_fd == -1) {
109                 DEBUG(0,("Failed to open nbench log\n"));
110                 return NT_STATUS_UNSUCCESSFUL;
111         }
112
113         ntvfs->private_data = nprivates;
114
115         status = ntvfs_next_connect(ntvfs, req, sharename);
116
117         return status;
118 }
119
120 /*
121   disconnect from a share
122 */
123 static NTSTATUS nbench_disconnect(struct ntvfs_module_context *ntvfs,
124                                   struct smbsrv_tcon *tcon)
125 {
126         struct nbench_private *nprivates = ntvfs->private_data;
127         NTSTATUS status;
128
129         close(nprivates->log_fd);
130
131         status = ntvfs_next_disconnect(ntvfs, tcon);
132
133         return status;
134 }
135
136 /*
137   delete a file - the dirtype specifies the file types to include in the search. 
138   The name can contain CIFS wildcards, but rarely does (except with OS/2 clients)
139 */
140 static void nbench_unlink_send(struct smbsrv_request *req)
141 {
142         struct smb_unlink *unl = req->async_states->private_data;
143
144         nbench_log(req, "Unlink \"%s\" 0x%x %s\n", 
145                    unl->in.pattern, unl->in.attrib, 
146                    get_nt_error_c_code(req->async_states->status));
147
148         PASS_THRU_REP_POST(req);
149 }
150
151 static NTSTATUS nbench_unlink(struct ntvfs_module_context *ntvfs,
152                               struct smbsrv_request *req, struct smb_unlink *unl)
153 {
154         NTSTATUS status;
155
156         PASS_THRU_REQ(ntvfs, req, unlink, unl, (ntvfs, req, unl));
157
158         return status;
159 }
160
161 /*
162   ioctl interface
163 */
164 static void nbench_ioctl_send(struct smbsrv_request *req)
165 {
166         nbench_log(req, "Ioctl - NOT HANDLED\n");
167
168         PASS_THRU_REP_POST(req);
169 }
170
171 static NTSTATUS nbench_ioctl(struct ntvfs_module_context *ntvfs,
172                              struct smbsrv_request *req, union smb_ioctl *io)
173 {
174         NTSTATUS status;
175
176         PASS_THRU_REQ(ntvfs, req, ioctl, io, (ntvfs, req, io));
177
178         return status;
179 }
180
181 /*
182   check if a directory exists
183 */
184 static void nbench_chkpath_send(struct smbsrv_request *req)
185 {
186         struct smb_chkpath *cp = req->async_states->private_data;
187
188         nbench_log(req, "Chkpath \"%s\" %s\n", 
189                    cp->in.path, 
190                    get_nt_error_c_code(req->async_states->status));
191
192         PASS_THRU_REP_POST(req);
193 }
194
195 static NTSTATUS nbench_chkpath(struct ntvfs_module_context *ntvfs,
196                                struct smbsrv_request *req, struct smb_chkpath *cp)
197 {
198         NTSTATUS status;
199
200         PASS_THRU_REQ(ntvfs, req, chkpath, cp, (ntvfs, req, cp));
201
202         return status;
203 }
204
205 /*
206   return info on a pathname
207 */
208 static void nbench_qpathinfo_send(struct smbsrv_request *req)
209 {
210         union smb_fileinfo *info = req->async_states->private_data;
211
212         nbench_log(req, "QUERY_PATH_INFORMATION \"%s\" %d %s\n", 
213                    info->generic.in.fname, 
214                    info->generic.level,
215                    get_nt_error_c_code(req->async_states->status));
216
217         PASS_THRU_REP_POST(req);
218 }
219
220 static NTSTATUS nbench_qpathinfo(struct ntvfs_module_context *ntvfs,
221                                  struct smbsrv_request *req, union smb_fileinfo *info)
222 {
223         NTSTATUS status;
224
225         PASS_THRU_REQ(ntvfs, req, qpathinfo, info, (ntvfs, req, info));
226
227         return status;
228 }
229
230 /*
231   query info on a open file
232 */
233 static void nbench_qfileinfo_send(struct smbsrv_request *req)
234 {
235         union smb_fileinfo *info = req->async_states->private_data;
236
237         nbench_log(req, "QUERY_FILE_INFORMATION %d %d %s\n", 
238                    info->generic.in.fnum, 
239                    info->generic.level,
240                    get_nt_error_c_code(req->async_states->status));
241
242         PASS_THRU_REP_POST(req);
243 }
244
245 static NTSTATUS nbench_qfileinfo(struct ntvfs_module_context *ntvfs,
246                                  struct smbsrv_request *req, union smb_fileinfo *info)
247 {
248         NTSTATUS status;
249
250         PASS_THRU_REQ(ntvfs, req, qfileinfo, info, (ntvfs, req, info));
251
252         return status;
253 }
254
255 /*
256   set info on a pathname
257 */
258 static void nbench_setpathinfo_send(struct smbsrv_request *req)
259 {
260         union smb_setfileinfo *st = req->async_states->private_data;
261
262         nbench_log(req, "SET_PATH_INFORMATION \"%s\" %d %s\n", 
263                    st->generic.file.fname, 
264                    st->generic.level,
265                    get_nt_error_c_code(req->async_states->status));
266
267         PASS_THRU_REP_POST(req);
268 }
269
270 static NTSTATUS nbench_setpathinfo(struct ntvfs_module_context *ntvfs,
271                                    struct smbsrv_request *req, union smb_setfileinfo *st)
272 {
273         NTSTATUS status;
274
275         PASS_THRU_REQ(ntvfs, req, setpathinfo, st, (ntvfs, req, st));
276
277         return status;
278 }
279
280 /*
281   open a file
282 */
283 static void nbench_openfile_send(struct smbsrv_request *req)
284 {
285         union smb_open *io = req->async_states->private_data;
286
287         switch (io->generic.level) {
288         case RAW_OPEN_NTCREATEX:
289                 if (!NT_STATUS_IS_OK(req->async_states->status)) {
290                         ZERO_STRUCT(io->ntcreatex.out);
291                 }
292                 nbench_log(req, "NTCreateX \"%s\" 0x%x 0x%x %d %s\n", 
293                            io->ntcreatex.in.fname, 
294                            io->ntcreatex.in.create_options, 
295                            io->ntcreatex.in.open_disposition, 
296                            io->ntcreatex.out.fnum,
297                            get_nt_error_c_code(req->async_states->status));
298                 break;
299
300         default:
301                 nbench_log(req, "Open-%d - NOT HANDLED\n",
302                            io->generic.level);
303                 break;
304         }
305
306         PASS_THRU_REP_POST(req);
307 }
308
309 static NTSTATUS nbench_openfile(struct ntvfs_module_context *ntvfs,
310                                 struct smbsrv_request *req, union smb_open *io)
311 {
312         NTSTATUS status;
313
314         PASS_THRU_REQ(ntvfs, req, openfile, io, (ntvfs, req, io));
315
316         return status;
317 }
318
319 /*
320   create a directory
321 */
322 static void nbench_mkdir_send(struct smbsrv_request *req)
323 {
324         nbench_log(req, "Mkdir - NOT HANDLED\n");
325
326         PASS_THRU_REP_POST(req);
327 }
328
329 static NTSTATUS nbench_mkdir(struct ntvfs_module_context *ntvfs,
330                              struct smbsrv_request *req, union smb_mkdir *md)
331 {
332         NTSTATUS status;
333
334         PASS_THRU_REQ(ntvfs, req, mkdir, md, (ntvfs, req, md));
335
336         return status;
337 }
338
339 /*
340   remove a directory
341 */
342 static void nbench_rmdir_send(struct smbsrv_request *req)
343 {
344         struct smb_rmdir *rd = req->async_states->private_data;
345
346         nbench_log(req, "Rmdir \"%s\" %s\n", 
347                    rd->in.path, 
348                    get_nt_error_c_code(req->async_states->status));
349
350         PASS_THRU_REP_POST(req);
351 }
352
353 static NTSTATUS nbench_rmdir(struct ntvfs_module_context *ntvfs,
354                              struct smbsrv_request *req, struct smb_rmdir *rd)
355 {
356         NTSTATUS status;
357
358         PASS_THRU_REQ(ntvfs, req, rmdir, rd, (ntvfs, req, rd));
359
360         return status;
361 }
362
363 /*
364   rename a set of files
365 */
366 static void nbench_rename_send(struct smbsrv_request *req)
367 {
368         union smb_rename *ren = req->async_states->private_data;
369
370         switch (ren->generic.level) {
371         case RAW_RENAME_RENAME:
372                 nbench_log(req, "Rename \"%s\" \"%s\" %s\n", 
373                            ren->rename.in.pattern1, 
374                            ren->rename.in.pattern2, 
375                            get_nt_error_c_code(req->async_states->status));
376                 break;
377
378         default:
379                 nbench_log(req, "Rename-%d - NOT HANDLED\n",
380                            ren->generic.level);
381                 break;
382         }
383
384         PASS_THRU_REP_POST(req);
385 }
386
387 static NTSTATUS nbench_rename(struct ntvfs_module_context *ntvfs,
388                               struct smbsrv_request *req, union smb_rename *ren)
389 {
390         NTSTATUS status;
391
392         PASS_THRU_REQ(ntvfs, req, rename, ren, (ntvfs, req, ren));
393
394         return status;
395 }
396
397 /*
398   copy a set of files
399 */
400 static void nbench_copy_send(struct smbsrv_request *req)
401 {
402         nbench_log(req, "Copy - NOT HANDLED\n");
403
404         PASS_THRU_REP_POST(req);
405 }
406
407 static NTSTATUS nbench_copy(struct ntvfs_module_context *ntvfs,
408                             struct smbsrv_request *req, struct smb_copy *cp)
409 {
410         NTSTATUS status;
411
412         PASS_THRU_REQ(ntvfs, req, copy, cp, (ntvfs, req, cp));
413
414         return status;
415 }
416
417 /*
418   read from a file
419 */
420 static void nbench_read_send(struct smbsrv_request *req)
421 {
422         union smb_read *rd = req->async_states->private_data;
423         
424         switch (rd->generic.level) {
425         case RAW_READ_READX:
426                 if (!NT_STATUS_IS_OK(req->async_states->status)) {
427                         ZERO_STRUCT(rd->readx.out);
428                 }
429                 nbench_log(req, "ReadX %d %d %d %d %s\n", 
430                            rd->readx.in.fnum, 
431                            (int)rd->readx.in.offset,
432                            rd->readx.in.maxcnt,
433                            rd->readx.out.nread,
434                            get_nt_error_c_code(req->async_states->status));
435                 break;
436         default:
437                 nbench_log(req, "Read-%d - NOT HANDLED\n",
438                            rd->generic.level);
439                 break;
440         }
441
442         PASS_THRU_REP_POST(req);
443 }
444
445 static NTSTATUS nbench_read(struct ntvfs_module_context *ntvfs,
446                             struct smbsrv_request *req, union smb_read *rd)
447 {
448         NTSTATUS status;
449
450         PASS_THRU_REQ(ntvfs, req, read, rd, (ntvfs, req, rd));
451
452         return status;
453 }
454
455 /*
456   write to a file
457 */
458 static void nbench_write_send(struct smbsrv_request *req)
459 {
460         union smb_write *wr = req->async_states->private_data;
461
462         switch (wr->generic.level) {
463         case RAW_WRITE_WRITEX:
464                 if (!NT_STATUS_IS_OK(req->async_states->status)) {
465                         ZERO_STRUCT(wr->writex.out);
466                 }
467                 nbench_log(req, "WriteX %d %d %d %d %s\n", 
468                            wr->writex.in.fnum, 
469                            (int)wr->writex.in.offset,
470                            wr->writex.in.count,
471                            wr->writex.out.nwritten,
472                            get_nt_error_c_code(req->async_states->status));
473                 break;
474
475         case RAW_WRITE_WRITE:
476                 if (!NT_STATUS_IS_OK(req->async_states->status)) {
477                         ZERO_STRUCT(wr->write.out);
478                 }
479                 nbench_log(req, "Write %d %d %d %d %s\n", 
480                            wr->write.in.fnum, 
481                            wr->write.in.offset,
482                            wr->write.in.count,
483                            wr->write.out.nwritten,
484                            get_nt_error_c_code(req->async_states->status));
485                 break;
486
487         default:
488                 nbench_log(req, "Write-%d - NOT HANDLED\n",
489                            wr->generic.level);
490                 break;
491         }
492
493         PASS_THRU_REP_POST(req);
494 }
495
496 static NTSTATUS nbench_write(struct ntvfs_module_context *ntvfs,
497                              struct smbsrv_request *req, union smb_write *wr)
498 {
499         NTSTATUS status;
500
501         PASS_THRU_REQ(ntvfs, req, write, wr, (ntvfs, req, wr));
502
503         return status;
504 }
505
506 /*
507   seek in a file
508 */
509 static void nbench_seek_send(struct smbsrv_request *req)
510 {
511         nbench_log(req, "Seek - NOT HANDLED\n");
512
513         PASS_THRU_REP_POST(req);
514 }
515
516 static NTSTATUS nbench_seek(struct ntvfs_module_context *ntvfs,
517                             struct smbsrv_request *req, struct smb_seek *io)
518 {
519         NTSTATUS status;
520
521         PASS_THRU_REQ(ntvfs, req, seek, io, (ntvfs, req, io));
522
523         return status;
524 }
525
526 /*
527   flush a file
528 */
529 static void nbench_flush_send(struct smbsrv_request *req)
530 {
531         struct smb_flush *io = req->async_states->private_data;
532
533         nbench_log(req, "Flush %d %s\n",
534                    io->in.fnum,
535                    get_nt_error_c_code(req->async_states->status));
536
537         PASS_THRU_REP_POST(req);
538 }
539
540 static NTSTATUS nbench_flush(struct ntvfs_module_context *ntvfs,
541                              struct smbsrv_request *req, struct smb_flush *io)
542 {
543         NTSTATUS status;
544
545         PASS_THRU_REQ(ntvfs, req, flush, io, (ntvfs, req, io));
546
547         return status;
548 }
549
550 /*
551   close a file
552 */
553 static void nbench_close_send(struct smbsrv_request *req)
554 {
555         union smb_close *io = req->async_states->private_data;
556
557         switch (io->generic.level) {
558         case RAW_CLOSE_CLOSE:
559                 nbench_log(req, "Close %d %s\n",
560                            io->close.in.fnum,
561                            get_nt_error_c_code(req->async_states->status));
562                 break;
563
564         default:
565                 nbench_log(req, "Close-%d - NOT HANDLED\n",
566                            io->generic.level);
567                 break;
568         }               
569
570         PASS_THRU_REP_POST(req);
571 }
572
573 static NTSTATUS nbench_close(struct ntvfs_module_context *ntvfs,
574                              struct smbsrv_request *req, union smb_close *io)
575 {
576         NTSTATUS status;
577
578         PASS_THRU_REQ(ntvfs, req, close, io, (ntvfs, req, io));
579
580         return status;
581 }
582
583 /*
584   exit - closing files
585 */
586 static void nbench_exit_send(struct smbsrv_request *req)
587 {
588         nbench_log(req, "Exit - NOT HANDLED\n");
589
590         PASS_THRU_REP_POST(req);
591 }
592
593 static NTSTATUS nbench_exit(struct ntvfs_module_context *ntvfs,
594                             struct smbsrv_request *req)
595 {
596         NTSTATUS status;
597
598         PASS_THRU_REQ(ntvfs, req, exit, NULL, (ntvfs, req));
599
600         return status;
601 }
602
603 /*
604   logoff - closing files
605 */
606 static void nbench_logoff_send(struct smbsrv_request *req)
607 {
608         nbench_log(req, "Logoff - NOT HANDLED\n");
609
610         PASS_THRU_REP_POST(req);
611 }
612
613 static NTSTATUS nbench_logoff(struct ntvfs_module_context *ntvfs,
614                               struct smbsrv_request *req)
615 {
616         NTSTATUS status;
617
618         PASS_THRU_REQ(ntvfs, req, logoff, NULL, (ntvfs, req));
619
620         return status;
621 }
622
623 /*
624   async_setup - send fn
625 */
626 static void nbench_async_setup_send(struct smbsrv_request *req)
627 {
628         PASS_THRU_REP_POST(req);
629 }
630
631 /*
632   async setup
633 */
634 static NTSTATUS nbench_async_setup(struct ntvfs_module_context *ntvfs,
635                                    struct smbsrv_request *req,
636                                    void *private)
637 {
638         NTSTATUS status;
639
640         PASS_THRU_REQ(ntvfs, req, async_setup, NULL, (ntvfs, req, private));
641
642         return status;
643 }
644
645 /*
646   lock a byte range
647 */
648 static void nbench_lock_send(struct smbsrv_request *req)
649 {
650         union smb_lock *lck = req->async_states->private_data;
651
652         if (lck->generic.level == RAW_LOCK_LOCKX &&
653             lck->lockx.in.lock_cnt == 1 &&
654             lck->lockx.in.ulock_cnt == 0) {
655                 nbench_log(req, "LockX %d %d %d %s\n", 
656                            lck->lockx.in.fnum,
657                            (int)lck->lockx.in.locks[0].offset,
658                            (int)lck->lockx.in.locks[0].count,
659                            get_nt_error_c_code(req->async_states->status));
660         } else if (lck->generic.level == RAW_LOCK_LOCKX &&
661                    lck->lockx.in.ulock_cnt == 1) {
662                 nbench_log(req, "UnlockX %d %d %d %s\n", 
663                            lck->lockx.in.fnum,
664                            (int)lck->lockx.in.locks[0].offset,
665                            (int)lck->lockx.in.locks[0].count,
666                            get_nt_error_c_code(req->async_states->status));
667         } else {
668                 nbench_log(req, "Lock-%d - NOT HANDLED\n", lck->generic.level);
669         }
670
671         PASS_THRU_REP_POST(req);
672 }
673
674 static NTSTATUS nbench_lock(struct ntvfs_module_context *ntvfs,
675                             struct smbsrv_request *req, union smb_lock *lck)
676 {
677         NTSTATUS status;
678
679         PASS_THRU_REQ(ntvfs, req, lock, lck, (ntvfs, req, lck));
680
681         return status;
682 }
683
684 /*
685   set info on a open file
686 */
687 static void nbench_setfileinfo_send(struct smbsrv_request *req)
688 {
689         union smb_setfileinfo *info = req->async_states->private_data;
690
691         nbench_log(req, "SET_FILE_INFORMATION %d %d %s\n", 
692                    info->generic.file.fnum,
693                    info->generic.level,
694                    get_nt_error_c_code(req->async_states->status));
695
696         PASS_THRU_REP_POST(req);
697 }
698
699 static NTSTATUS nbench_setfileinfo(struct ntvfs_module_context *ntvfs,
700                                    struct smbsrv_request *req, 
701                                    union smb_setfileinfo *info)
702 {
703         NTSTATUS status;
704
705         PASS_THRU_REQ(ntvfs, req, setfileinfo, info, (ntvfs, req, info));
706
707         return status;
708 }
709
710 /*
711   return filesystem space info
712 */
713 static void nbench_fsinfo_send(struct smbsrv_request *req)
714 {
715         union smb_fsinfo *fs = req->async_states->private_data;
716
717         nbench_log(req, "QUERY_FS_INFORMATION %d %s\n", 
718                    fs->generic.level, 
719                    get_nt_error_c_code(req->async_states->status));
720
721         PASS_THRU_REP_POST(req);
722 }
723
724 static NTSTATUS nbench_fsinfo(struct ntvfs_module_context *ntvfs,
725                               struct smbsrv_request *req, union smb_fsinfo *fs)
726 {
727         NTSTATUS status;
728
729         PASS_THRU_REQ(ntvfs, req, fsinfo, fs, (ntvfs, req, fs));
730
731         return status;
732 }
733
734 /*
735   return print queue info
736 */
737 static void nbench_lpq_send(struct smbsrv_request *req)
738 {
739         union smb_lpq *lpq = req->async_states->private_data;
740
741         nbench_log(req, "Lpq-%d - NOT HANDLED\n", lpq->generic.level);
742
743         PASS_THRU_REP_POST(req);
744 }
745
746 static NTSTATUS nbench_lpq(struct ntvfs_module_context *ntvfs,
747                            struct smbsrv_request *req, union smb_lpq *lpq)
748 {
749         NTSTATUS status;
750
751         PASS_THRU_REQ(ntvfs, req, lpq, lpq, (ntvfs, req, lpq));
752
753         return status;
754 }
755
756 /* 
757    list files in a directory matching a wildcard pattern
758 */
759 static void nbench_search_first_send(struct smbsrv_request *req)
760 {
761         union smb_search_first *io = req->async_states->private_data;
762         
763         switch (io->generic.level) {
764         case RAW_SEARCH_BOTH_DIRECTORY_INFO:
765                 if (NT_STATUS_IS_ERR(req->async_states->status)) {
766                         ZERO_STRUCT(io->t2ffirst.out);
767                 }
768                 nbench_log(req, "FIND_FIRST \"%s\" %d %d %d %s\n", 
769                            io->t2ffirst.in.pattern,
770                            io->generic.level,
771                            io->t2ffirst.in.max_count,
772                            io->t2ffirst.out.count,
773                            get_nt_error_c_code(req->async_states->status));
774                 break;
775                 
776         default:
777                 nbench_log(req, "Search-%d - NOT HANDLED\n", io->generic.level);
778                 break;
779         }
780
781         PASS_THRU_REP_POST(req);
782 }
783
784 static NTSTATUS nbench_search_first(struct ntvfs_module_context *ntvfs,
785                                     struct smbsrv_request *req, union smb_search_first *io, 
786                                     void *search_private, 
787                                     BOOL (*callback)(void *, union smb_search_data *))
788 {
789         NTSTATUS status;
790
791         PASS_THRU_REQ(ntvfs, req, search_first, io, (ntvfs, req, io, search_private, callback));
792
793         return status;
794 }
795
796 /* continue a search */
797 static void nbench_search_next_send(struct smbsrv_request *req)
798 {
799         union smb_search_next *io = req->async_states->private_data;
800
801         nbench_log(req, "Searchnext-%d - NOT HANDLED\n", io->generic.level);
802
803         PASS_THRU_REP_POST(req);
804 }
805
806 static NTSTATUS nbench_search_next(struct ntvfs_module_context *ntvfs,
807                                    struct smbsrv_request *req, union smb_search_next *io, 
808                                    void *search_private, 
809                                    BOOL (*callback)(void *, union smb_search_data *))
810 {
811         NTSTATUS status;
812
813         PASS_THRU_REQ(ntvfs, req, search_next, io, (ntvfs, req, io, search_private, callback));
814
815         return status;
816 }
817
818 /* close a search */
819 static void nbench_search_close_send(struct smbsrv_request *req)
820 {
821         union smb_search_close *io = req->async_states->private_data;
822
823         nbench_log(req, "Searchclose-%d - NOT HANDLED\n", io->generic.level);
824
825         PASS_THRU_REP_POST(req);
826 }
827
828 static NTSTATUS nbench_search_close(struct ntvfs_module_context *ntvfs,
829                                     struct smbsrv_request *req, union smb_search_close *io)
830 {
831         NTSTATUS status;
832
833         PASS_THRU_REQ(ntvfs, req, search_close, io, (ntvfs, req, io));
834
835         return status;
836 }
837
838 /* SMBtrans - not used on file shares */
839 static void nbench_trans_send(struct smbsrv_request *req)
840 {
841         nbench_log(req, "Trans - NOT HANDLED\n");
842
843         PASS_THRU_REP_POST(req);
844 }
845
846 static NTSTATUS nbench_trans(struct ntvfs_module_context *ntvfs,
847                              struct smbsrv_request *req, struct smb_trans2 *trans2)
848 {
849         NTSTATUS status;
850
851         PASS_THRU_REQ(ntvfs, req, trans, trans2, (ntvfs, req, trans2));
852
853         return status;
854 }
855
856 /*
857   initialise the nbench backend, registering ourselves with the ntvfs subsystem
858  */
859 NTSTATUS ntvfs_nbench_init(void)
860 {
861         NTSTATUS ret;
862         struct ntvfs_ops ops;
863
864         ZERO_STRUCT(ops);
865
866         /* fill in the name and type */
867         ops.name = "nbench";
868         ops.type = NTVFS_DISK;
869         
870         /* fill in all the operations */
871         ops.connect = nbench_connect;
872         ops.disconnect = nbench_disconnect;
873         ops.unlink = nbench_unlink;
874         ops.chkpath = nbench_chkpath;
875         ops.qpathinfo = nbench_qpathinfo;
876         ops.setpathinfo = nbench_setpathinfo;
877         ops.openfile = nbench_openfile;
878         ops.mkdir = nbench_mkdir;
879         ops.rmdir = nbench_rmdir;
880         ops.rename = nbench_rename;
881         ops.copy = nbench_copy;
882         ops.ioctl = nbench_ioctl;
883         ops.read = nbench_read;
884         ops.write = nbench_write;
885         ops.seek = nbench_seek;
886         ops.flush = nbench_flush;       
887         ops.close = nbench_close;
888         ops.exit = nbench_exit;
889         ops.lock = nbench_lock;
890         ops.setfileinfo = nbench_setfileinfo;
891         ops.qfileinfo = nbench_qfileinfo;
892         ops.fsinfo = nbench_fsinfo;
893         ops.lpq = nbench_lpq;
894         ops.search_first = nbench_search_first;
895         ops.search_next = nbench_search_next;
896         ops.search_close = nbench_search_close;
897         ops.trans = nbench_trans;
898         ops.logoff = nbench_logoff;
899         ops.async_setup = nbench_async_setup;
900
901         /* we don't register a trans2 handler as we want to be able to
902            log individual trans2 requests */
903         ops.trans2 = NULL;
904
905         /* register ourselves with the NTVFS subsystem. */
906         ret = register_backend("ntvfs", &ops);
907
908         if (!NT_STATUS_IS_OK(ret)) {
909                 DEBUG(0,("Failed to register nbench backend!\n"));
910         }
911         
912         return ret;
913 }