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