r19281: Generalize what we do for the RAW-QFILEINFO test call so that the same process
[Samba/ekacnet.git] / source4 / torture / misc.c
blob62b956337c91604242d89c8b74069bd1d8761c49
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Tridgell 1997-2003
5 Copyright (C) Jelmer Vernooij 2006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "system/time.h"
25 #include "system/wait.h"
26 #include "system/filesys.h"
27 #include "libcli/raw/ioctl.h"
28 #include "libcli/libcli.h"
29 #include "lib/events/events.h"
30 #include "libcli/resolve/resolve.h"
31 #include "auth/credentials/credentials.h"
32 #include "librpc/gen_ndr/ndr_nbt.h"
33 #include "torture/torture.h"
34 #include "torture/util.h"
35 #include "libcli/smb_composite/smb_composite.h"
36 #include "libcli/composite/composite.h"
38 extern struct cli_credentials *cmdline_credentials;
39 void benchrw_callback(struct smbcli_request *req);
40 enum benchrw_stage {
41 START,
42 OPEN_CONNECTION,
43 CLEANUP_TESTDIR,
44 MK_TESTDIR,
45 OPEN_FILE,
46 INITIAL_WRITE,
47 READ_WRITE_DATA,
48 MAX_OPS_REACHED,
49 ERROR,
50 CLOSE_FILE,
51 CLEANUP,
52 FINISHED
55 struct benchrw_state{
56 char *dname;
57 char *fname;
58 uint16_t fnum;
59 int nr;
60 struct smbcli_tree *cli;
61 uint8_t *buffer;
62 int writecnt;
63 int readcnt;
64 int completed;
65 TALLOC_CTX *mem_ctx;
66 void *req_params;
67 enum benchrw_stage mode;
68 struct params{
69 struct unclist{
70 const char *host;
71 const char *share;
72 } **unc;
73 const char *workgroup;
74 int retry;
75 unsigned int writeblocks;
76 unsigned int blocksize;
77 unsigned int writeratio;
78 } *lp_params;
81 static BOOL wait_lock(struct smbcli_state *c, int fnum, uint32_t offset, uint32_t len)
83 while (NT_STATUS_IS_ERR(smbcli_lock(c->tree, fnum, offset, len, -1, WRITE_LOCK))) {
84 if (!check_error(__location__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
86 return True;
90 static BOOL rw_torture(struct smbcli_state *c)
92 const char *lockfname = "\\torture.lck";
93 char *fname;
94 int fnum;
95 int fnum2;
96 pid_t pid2, pid = getpid();
97 int i, j;
98 uint8_t buf[1024];
99 BOOL correct = True;
101 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL,
102 DENY_NONE);
103 if (fnum2 == -1)
104 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
105 if (fnum2 == -1) {
106 printf("open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree));
107 return False;
111 for (i=0;i<torture_numops;i++) {
112 uint_t n = (uint_t)random()%10;
113 if (i % 10 == 0) {
114 printf("%d\r", i); fflush(stdout);
116 asprintf(&fname, "\\torture.%u", n);
118 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
119 return False;
122 fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
123 if (fnum == -1) {
124 printf("open failed (%s)\n", smbcli_errstr(c->tree));
125 correct = False;
126 break;
129 if (smbcli_write(c->tree, fnum, 0, &pid, 0, sizeof(pid)) != sizeof(pid)) {
130 printf("write failed (%s)\n", smbcli_errstr(c->tree));
131 correct = False;
134 for (j=0;j<50;j++) {
135 if (smbcli_write(c->tree, fnum, 0, buf,
136 sizeof(pid)+(j*sizeof(buf)),
137 sizeof(buf)) != sizeof(buf)) {
138 printf("write failed (%s)\n", smbcli_errstr(c->tree));
139 correct = False;
143 pid2 = 0;
145 if (smbcli_read(c->tree, fnum, &pid2, 0, sizeof(pid)) != sizeof(pid)) {
146 printf("read failed (%s)\n", smbcli_errstr(c->tree));
147 correct = False;
150 if (pid2 != pid) {
151 printf("data corruption!\n");
152 correct = False;
155 if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
156 printf("close failed (%s)\n", smbcli_errstr(c->tree));
157 correct = False;
160 if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) {
161 printf("unlink failed (%s)\n", smbcli_errstr(c->tree));
162 correct = False;
165 if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
166 printf("unlock failed (%s)\n", smbcli_errstr(c->tree));
167 correct = False;
169 free(fname);
172 smbcli_close(c->tree, fnum2);
173 smbcli_unlink(c->tree, lockfname);
175 printf("%d\n", i);
177 return correct;
180 static BOOL run_torture(struct smbcli_state *cli, int dummy)
182 BOOL ret;
184 ret = rw_torture(cli);
186 if (!torture_close_connection(cli)) {
187 ret = False;
190 return ret;
195 see how many RPC pipes we can open at once
197 static BOOL run_pipe_number(struct torture_context *torture)
199 struct smbcli_state *cli1;
200 const char *pipe_name = "\\WKSSVC";
201 int fnum;
202 int num_pipes = 0;
204 printf("starting pipenumber test\n");
205 if (!torture_open_connection(&cli1, 0)) {
206 return False;
209 while(1) {
210 fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
211 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
213 if (fnum == -1) {
214 printf("Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree));
215 break;
217 num_pipes++;
218 printf("%d\r", num_pipes);
219 fflush(stdout);
222 printf("pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
223 torture_close_connection(cli1);
224 return True;
231 open N connections to the server and just hold them open
232 used for testing performance when there are N idle users
233 already connected
235 static BOOL torture_holdcon(struct torture_context *torture)
237 int i;
238 struct smbcli_state **cli;
239 int num_dead = 0;
241 printf("Opening %d connections\n", torture_numops);
243 cli = malloc_array_p(struct smbcli_state *, torture_numops);
245 for (i=0;i<torture_numops;i++) {
246 if (!torture_open_connection(&cli[i], i)) {
247 return False;
249 printf("opened %d connections\r", i);
250 fflush(stdout);
253 printf("\nStarting pings\n");
255 while (1) {
256 for (i=0;i<torture_numops;i++) {
257 NTSTATUS status;
258 if (cli[i]) {
259 status = smbcli_chkpath(cli[i]->tree, "\\");
260 if (!NT_STATUS_IS_OK(status)) {
261 printf("Connection %d is dead\n", i);
262 cli[i] = NULL;
263 num_dead++;
265 usleep(100);
269 if (num_dead == torture_numops) {
270 printf("All connections dead - finishing\n");
271 break;
274 printf(".");
275 fflush(stdout);
278 return True;
282 test how many open files this server supports on the one socket
284 static BOOL run_maxfidtest(struct smbcli_state *cli, int dummy)
286 #define MAXFID_TEMPLATE "\\maxfid\\fid%d\\maxfid.%d.%d"
287 char *fname;
288 int fnums[0x11000], i;
289 int retries=4, maxfid;
290 BOOL correct = True;
292 if (retries <= 0) {
293 printf("failed to connect\n");
294 return False;
297 if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
298 printf("Failed to deltree \\maxfid - %s\n",
299 smbcli_errstr(cli->tree));
300 return False;
302 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\maxfid"))) {
303 printf("Failed to mkdir \\maxfid, error=%s\n",
304 smbcli_errstr(cli->tree));
305 return False;
308 printf("Testing maximum number of open files\n");
310 for (i=0; i<0x11000; i++) {
311 if (i % 1000 == 0) {
312 asprintf(&fname, "\\maxfid\\fid%d", i/1000);
313 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) {
314 printf("Failed to mkdir %s, error=%s\n",
315 fname, smbcli_errstr(cli->tree));
316 return False;
318 free(fname);
320 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
321 if ((fnums[i] = smbcli_open(cli->tree, fname,
322 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
323 -1) {
324 printf("open of %s failed (%s)\n",
325 fname, smbcli_errstr(cli->tree));
326 printf("maximum fnum is %d\n", i);
327 break;
329 free(fname);
330 printf("%6d\r", i);
332 printf("%6d\n", i);
333 i--;
335 maxfid = i;
337 printf("cleaning up\n");
338 for (i=0;i<maxfid/2;i++) {
339 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
340 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) {
341 printf("Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree));
343 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
344 printf("unlink of %s failed (%s)\n",
345 fname, smbcli_errstr(cli->tree));
346 correct = False;
348 free(fname);
350 asprintf(&fname, MAXFID_TEMPLATE, (maxfid-i)/1000, maxfid-i,(int)getpid());
351 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[maxfid-i]))) {
352 printf("Close of fnum %d failed - %s\n", fnums[maxfid-i], smbcli_errstr(cli->tree));
354 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
355 printf("unlink of %s failed (%s)\n",
356 fname, smbcli_errstr(cli->tree));
357 correct = False;
359 free(fname);
361 printf("%6d %6d\r", i, maxfid-i);
363 printf("%6d\n", 0);
365 if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
366 printf("Failed to deltree \\maxfid - %s\n",
367 smbcli_errstr(cli->tree));
368 return False;
371 printf("maxfid test finished\n");
372 if (!torture_close_connection(cli)) {
373 correct = False;
375 return correct;
376 #undef MAXFID_TEMPLATE
382 sees what IOCTLs are supported
384 static BOOL torture_ioctl_test(struct torture_context *torture)
386 struct smbcli_state *cli;
387 uint16_t device, function;
388 int fnum;
389 const char *fname = "\\ioctl.dat";
390 NTSTATUS status;
391 union smb_ioctl parms;
392 TALLOC_CTX *mem_ctx;
394 if (!torture_open_connection(&cli, 0)) {
395 return False;
398 mem_ctx = talloc_named_const(torture, 0, "ioctl_test");
400 printf("starting ioctl test\n");
402 smbcli_unlink(cli->tree, fname);
404 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
405 if (fnum == -1) {
406 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
407 return False;
410 parms.ioctl.level = RAW_IOCTL_IOCTL;
411 parms.ioctl.in.file.fnum = fnum;
412 parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
413 status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
414 printf("ioctl job info: %s\n", smbcli_errstr(cli->tree));
416 for (device=0;device<0x100;device++) {
417 printf("testing device=0x%x\n", device);
418 for (function=0;function<0x100;function++) {
419 parms.ioctl.in.request = (device << 16) | function;
420 status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
422 if (NT_STATUS_IS_OK(status)) {
423 printf("ioctl device=0x%x function=0x%x OK : %d bytes\n",
424 device, function, (int)parms.ioctl.out.blob.length);
429 if (!torture_close_connection(cli)) {
430 return False;
433 return True;
437 init params using lp_parm_xxx
438 return number of unclist entries
440 int init_benchrw_params(TALLOC_CTX *mem_ctx,struct params *lpar)
442 char **unc_list = NULL;
443 int num_unc_names = 0, conn_index=0, empty_lines=0;
444 const char *p;
445 lpar->retry = lp_parm_int(-1, "torture", "retry",3);
446 lpar->blocksize = lp_parm_int(-1, "torture", "blocksize",65535);
447 lpar->writeblocks = lp_parm_int(-1, "torture", "writeblocks",15);
448 lpar->writeratio = lp_parm_int(-1, "torture", "writeratio",5);
449 lpar->workgroup = lp_workgroup();
451 p = lp_parm_string(-1, "torture", "unclist");
452 if (p) {
453 char *h, *s;
454 unc_list = file_lines_load(p, &num_unc_names, NULL);
455 if (!unc_list || num_unc_names <= 0) {
456 printf("Failed to load unc names list from '%s'\n", p);
457 exit(1);
460 lpar->unc = talloc_array(mem_ctx, struct unclist *, (num_unc_names-empty_lines));
461 for(conn_index = 0; conn_index < num_unc_names; conn_index++) {
462 /* ignore empty lines */
463 if(strlen(unc_list[conn_index % num_unc_names])==0){
464 empty_lines++;
465 continue;
467 if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
468 NULL, &h, &s)) {
469 printf("Failed to parse UNC name %s\n",
470 unc_list[conn_index % num_unc_names]);
471 exit(1);
473 lpar->unc[conn_index-empty_lines] = talloc(mem_ctx,struct unclist);
474 lpar->unc[conn_index-empty_lines]->host = h;
475 lpar->unc[conn_index-empty_lines]->share = s;
477 return num_unc_names-empty_lines;
478 }else{
479 lpar->unc = talloc_array(mem_ctx, struct unclist *, 1);
480 lpar->unc[0] = talloc(mem_ctx,struct unclist);
481 lpar->unc[0]->host = lp_parm_string(-1, "torture", "host");
482 lpar->unc[0]->share = lp_parm_string(-1, "torture", "share");
483 return 1;
488 Called when the reads & writes are finished. closes the file.
490 NTSTATUS benchrw_close(struct smbcli_request *req,
491 struct benchrw_state *state)
493 union smb_close close_parms;
495 NT_STATUS_NOT_OK_RETURN(req->status);
497 printf("Close file %d (%d)\n",state->nr,state->fnum);
498 close_parms.close.level = RAW_CLOSE_CLOSE;
499 close_parms.close.in.file.fnum = state->fnum ;
500 close_parms.close.in.write_time = 0;
501 state->mode=CLOSE_FILE;
503 req = smb_raw_close_send(state->cli, &close_parms);
504 NT_STATUS_HAVE_NO_MEMORY(req);
505 /*register the callback function!*/
506 req->async.fn = benchrw_callback;
507 req->async.private = state;
509 return NT_STATUS_OK;
513 Called when the initial write is completed is done. write or read a file.
515 NTSTATUS benchrw_readwrite(struct smbcli_request *req,
516 struct benchrw_state *state)
518 union smb_read rd;
519 union smb_write wr;
521 NT_STATUS_NOT_OK_RETURN(req->status);
523 state->completed++;
524 /*rotate between writes and reads*/
525 if( state->completed % state->lp_params->writeratio == 0){
526 printf("Callback WRITE file:%d (%d/%d)\n",
527 state->nr,state->completed,torture_numops);
528 wr.generic.level = RAW_WRITE_WRITEX ;
529 wr.writex.in.file.fnum = state->fnum ;
530 wr.writex.in.offset = 0;
531 wr.writex.in.wmode = 0 ;
532 wr.writex.in.remaining = 0;
533 wr.writex.in.count = state->lp_params->blocksize;
534 wr.writex.in.data = state->buffer;
535 state->readcnt=0;
536 req = smb_raw_write_send(state->cli,&wr);
537 }else{
538 printf("Callback READ file:%d (%d/%d) Offset:%d\n",
539 state->nr,state->completed,torture_numops,
540 (state->readcnt*state->lp_params->blocksize));
541 rd.generic.level = RAW_READ_READ ;
542 rd.read.in.file.fnum = state->fnum ;
543 rd.read.in.offset = state->readcnt *
544 state->lp_params->blocksize;
545 rd.read.in.count = state->lp_params->blocksize;
546 rd.read.in.remaining = 0 ;
547 rd.read.out.data = state->buffer;
548 if(state->readcnt < state->lp_params->writeblocks){
549 state->readcnt++;
550 }else{
551 /*start reading from beginn of file*/
552 state->readcnt=0;
554 req = smb_raw_read_send(state->cli,&rd);
556 NT_STATUS_HAVE_NO_MEMORY(req);
557 /*register the callback function!*/
558 req->async.fn = benchrw_callback;
559 req->async.private = state;
561 return NT_STATUS_OK;
565 Called when the open is done. writes to the file.
567 NTSTATUS benchrw_open(struct smbcli_request *req,
568 struct benchrw_state *state)
570 union smb_write wr;
571 if(state->mode == OPEN_FILE){
572 NTSTATUS status;
573 status = smb_raw_open_recv(req,state->mem_ctx,(
574 union smb_open*)state->req_params);
575 NT_STATUS_NOT_OK_RETURN(status);
577 state->fnum = ((union smb_open*)state->req_params)
578 ->openx.out.file.fnum;
579 printf("File opened (%d)\n",state->fnum);
580 state->mode=INITIAL_WRITE;
583 printf("Write initial test file:%d (%d/%d)\n",state->nr,
584 (state->writecnt+1)*state->lp_params->blocksize,
585 (state->lp_params->writeblocks*state->lp_params->blocksize));
586 wr.generic.level = RAW_WRITE_WRITEX ;
587 wr.writex.in.file.fnum = state->fnum ;
588 wr.writex.in.offset = state->writecnt *
589 state->lp_params->blocksize;
590 wr.writex.in.wmode = 0 ;
591 wr.writex.in.remaining = (state->lp_params->writeblocks *
592 state->lp_params->blocksize)-
593 ((state->writecnt+1)*state->
594 lp_params->blocksize);
595 wr.writex.in.count = state->lp_params->blocksize;
596 wr.writex.in.data = state->buffer;
597 state->writecnt++;
598 if(state->writecnt == state->lp_params->writeblocks){
599 state->mode=READ_WRITE_DATA;
601 req = smb_raw_write_send(state->cli,&wr);
602 NT_STATUS_HAVE_NO_MEMORY(req);
604 /*register the callback function!*/
605 req->async.fn = benchrw_callback;
606 req->async.private = state;
607 return NT_STATUS_OK;
611 Called when the mkdir is done. Opens a file.
613 NTSTATUS benchrw_mkdir(struct smbcli_request *req,
614 struct benchrw_state *state)
616 union smb_open *open_parms;
617 uint8_t *writedata;
619 NT_STATUS_NOT_OK_RETURN(req->status);
621 /* open/create the files */
622 printf("Open File %d/%d\n",state->nr+1,torture_nprocs);
623 open_parms=talloc_zero(state->mem_ctx, union smb_open);
624 NT_STATUS_HAVE_NO_MEMORY(open_parms);
625 open_parms->openx.level = RAW_OPEN_OPENX;
626 open_parms->openx.in.flags = 0;
627 open_parms->openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
628 open_parms->openx.in.search_attrs =
629 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
630 open_parms->openx.in.file_attrs = 0;
631 open_parms->openx.in.write_time = 0;
632 open_parms->openx.in.open_func = OPENX_OPEN_FUNC_CREATE;
633 open_parms->openx.in.size = 0;
634 open_parms->openx.in.timeout = 0;
635 open_parms->openx.in.fname = state->fname;
637 writedata = talloc_size(state->mem_ctx,state->lp_params->blocksize);
638 NT_STATUS_HAVE_NO_MEMORY(writedata);
639 generate_random_buffer(writedata,state->lp_params->blocksize);
640 state->buffer=writedata;
641 state->writecnt=1;
642 state->readcnt=0;
643 state->req_params=open_parms;
644 state->mode=OPEN_FILE;
646 req = smb_raw_open_send(state->cli,open_parms);
647 NT_STATUS_HAVE_NO_MEMORY(req);
649 /*register the callback function!*/
650 req->async.fn = benchrw_callback;
651 req->async.private = state;
653 return NT_STATUS_OK;
657 handler for completion of a sub-request of the bench-rw test
659 void benchrw_callback(struct smbcli_request *req)
661 struct benchrw_state *state = req->async.private;
663 /*dont send new requests when torture_numops is reached*/
664 if(state->completed >= torture_numops){
665 state->completed=0;
666 state->mode=MAX_OPS_REACHED;
669 switch (state->mode) {
671 case MK_TESTDIR:
672 if (!NT_STATUS_IS_OK(benchrw_mkdir(req,state))) {
673 printf("Failed to create the test directory - %s\n",
674 nt_errstr(req->status));
675 state->mode=ERROR;
676 return;
678 break;
679 case OPEN_FILE:
680 case INITIAL_WRITE:
681 if (!NT_STATUS_IS_OK(benchrw_open(req,state))){
682 printf("Failed to open/write the file - %s\n",
683 nt_errstr(req->status));
684 state->mode=ERROR;
685 return;
687 break;
688 case READ_WRITE_DATA:
689 if (!NT_STATUS_IS_OK(benchrw_readwrite(req,state))){
690 printf("Failed to read/write the file - %s\n",
691 nt_errstr(req->status));
692 state->mode=ERROR;
693 return;
695 break;
696 case MAX_OPS_REACHED:
697 if (!NT_STATUS_IS_OK(benchrw_close(req,state))){
698 printf("Failed to read/write/close the file - %s\n",
699 nt_errstr(req->status));
700 state->mode=ERROR;
701 return;
703 break;
704 case CLOSE_FILE:
705 printf("File %d closed\n",state->nr);
706 if (!NT_STATUS_IS_OK(req->status)) {
707 printf("Failed to close the file - %s\n",
708 nt_errstr(req->status));
709 state->mode=ERROR;
710 return;
712 state->mode=CLEANUP;
713 return;
714 default:
715 break;
720 /* open connection async callback function*/
721 void async_open_callback(struct composite_context *con)
723 struct benchrw_state *state = con->async.private_data;
724 int retry = state->lp_params->retry;
726 if (NT_STATUS_IS_OK(con->status)) {
727 state->cli=((struct smb_composite_connect*)
728 state->req_params)->out.tree;
729 state->mode=CLEANUP_TESTDIR;
730 }else{
731 if(state->writecnt < retry){
732 printf("Failed to open connection:%d, Retry (%d/%d)\n",
733 state->nr,state->writecnt,retry);
734 state->writecnt++;
735 state->mode=START;
736 usleep(1000);
737 }else{
738 printf("Failed to open connection (%d) - %s\n",
739 state->nr, nt_errstr(con->status));
740 state->mode=ERROR;
742 return;
747 establishs a smbcli_tree from scratch (async)
749 struct composite_context *torture_connect_async(
750 struct smb_composite_connect *smb,
751 TALLOC_CTX *mem_ctx,
752 struct event_context *ev,
753 const char *host,
754 const char *share,
755 const char *workgroup)
757 printf("Open Connection to %s/%s\n",host,share);
758 smb->in.dest_host=talloc_strdup(mem_ctx,host);
759 smb->in.service=talloc_strdup(mem_ctx,share);
760 smb->in.port=0;
761 smb->in.called_name = strupper_talloc(mem_ctx, host);
762 smb->in.service_type=NULL;
763 smb->in.credentials=cmdline_credentials;
764 smb->in.fallback_to_anonymous=False;
765 smb->in.workgroup=workgroup;
767 return smb_composite_connect_send(smb,mem_ctx,ev);
770 static BOOL run_benchrw(struct torture_context *torture)
772 struct smb_composite_connect *smb_con;
773 const char *fname = "\\rwtest.dat";
774 struct smbcli_request *req;
775 struct benchrw_state **state;
776 int i , num_unc_names;
777 TALLOC_CTX *mem_ctx;
778 struct event_context *ev ;
779 struct composite_context *req1;
780 struct params lpparams;
781 union smb_mkdir parms;
782 int finished = 0;
783 BOOL success=True;
785 printf("Start BENCH-READWRITE num_ops=%d num_nprocs=%d\n",
786 torture_numops,torture_nprocs);
788 /*init talloc context*/
789 mem_ctx = talloc_named_const(torture, 0, "bench-readwrite");
790 ev = event_context_init(mem_ctx);
791 state = talloc_array(mem_ctx, struct benchrw_state *, torture_nprocs);
793 /* init params using lp_parm_xxx */
794 num_unc_names = init_benchrw_params(mem_ctx,&lpparams);
796 /* init private data structs*/
797 for(i = 0; i<torture_nprocs;i++){
798 state[i]=talloc(mem_ctx,struct benchrw_state);
799 state[i]->completed=0;
800 state[i]->lp_params=&lpparams;
801 state[i]->nr=i;
802 state[i]->dname=talloc_asprintf(mem_ctx,"benchrw%d",i);
803 state[i]->fname=talloc_asprintf(mem_ctx,"%s%s",
804 state[i]->dname,fname);
805 state[i]->mode=START;
806 state[i]->writecnt=0;
809 printf("Starting async requests\n");
810 while(finished != torture_nprocs){
811 finished=0;
812 for(i = 0; i<torture_nprocs;i++){
813 switch (state[i]->mode){
814 /*open multiple connections with the same userid */
815 case START:
816 smb_con = talloc(mem_ctx,struct smb_composite_connect) ;
817 state[i]->req_params=smb_con;
818 state[i]->mode=OPEN_CONNECTION;
819 req1 = torture_connect_async(smb_con,
820 mem_ctx,ev,
821 lpparams.unc[i % num_unc_names]->host,
822 lpparams.unc[i % num_unc_names]->share,
823 lpparams.workgroup);
824 /* register callback fn + private data */
825 req1->async.fn = async_open_callback;
826 req1->async.private_data=state[i];
827 break;
828 /*setup test dirs (sync)*/
829 case CLEANUP_TESTDIR:
830 printf("Setup test dir %d\n",i);
831 smb_raw_exit(state[i]->cli->session);
832 if (smbcli_deltree(state[i]->cli,
833 state[i]->dname) == -1) {
834 printf("Unable to delete %s - %s\n",
835 state[i]->dname,
836 smbcli_errstr(state[i]->cli));
837 state[i]->mode=ERROR;
838 break;
840 state[i]->mode=MK_TESTDIR;
841 parms.mkdir.level = RAW_MKDIR_MKDIR;
842 parms.mkdir.in.path = state[i]->dname;
843 req = smb_raw_mkdir_send(state[i]->cli,&parms);
844 /* register callback fn + private data */
845 req->async.fn = benchrw_callback;
846 req->async.private=state[i];
847 break;
848 /* error occured , finish */
849 case ERROR:
850 finished++;
851 success=False;
852 break;
853 /* cleanup , close connection */
854 case CLEANUP:
855 printf("Deleting test dir %s %d/%d\n",state[i]->dname,
856 i+1,torture_nprocs);
857 smbcli_deltree(state[i]->cli,state[i]->dname);
858 if (NT_STATUS_IS_ERR(smb_tree_disconnect(
859 state[i]->cli))) {
860 printf("ERROR: Tree disconnect failed");
861 state[i]->mode=ERROR;
862 break;
864 state[i]->mode=FINISHED;
865 case FINISHED:
866 finished++;
867 break;
868 default:
869 event_loop_once(ev);
874 printf("BENCH-READWRITE done. Closing connections.\n");
876 /*free all allocated memory*/
877 talloc_free(mem_ctx);
879 return success;
883 NTSTATUS torture_misc_init(void)
885 register_torture_op("BENCH-HOLDCON", torture_holdcon);
886 register_torture_op("SCAN-PIPE_NUMBER", run_pipe_number);
887 register_torture_op("SCAN-IOCTL", torture_ioctl_test);
888 register_torture_op("BENCH-READWRITE", run_benchrw);
889 register_torture_multi_op("BENCH-TORTURE", run_torture);
890 register_torture_multi_op("SCAN-MAXFID", run_maxfidtest);
892 return NT_STATUS_OK;