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