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