r23506: Turn back to RAW_READ_READ because buildfarm fails. Investigating.
[Samba/gbeck.git] / source4 / torture / basic / misc.c
blob12eec9d551cc28ed3559c358038b0f7d960b2db7
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;
40 static BOOL wait_lock(struct smbcli_state *c, int fnum, uint32_t offset, uint32_t len)
42 while (NT_STATUS_IS_ERR(smbcli_lock(c->tree, fnum, offset, len, -1, WRITE_LOCK))) {
43 if (!check_error(__location__, c, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
45 return True;
49 static BOOL rw_torture(struct torture_context *tctx, struct smbcli_state *c)
51 const char *lockfname = "\\torture.lck";
52 char *fname;
53 int fnum;
54 int fnum2;
55 pid_t pid2, pid = getpid();
56 int i, j;
57 uint8_t buf[1024];
58 BOOL correct = True;
60 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL,
61 DENY_NONE);
62 if (fnum2 == -1)
63 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
64 if (fnum2 == -1) {
65 torture_comment(tctx, "open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree));
66 return False;
69 generate_random_buffer(buf, sizeof(buf));
71 for (i=0;i<torture_numops;i++) {
72 uint_t n = (uint_t)random()%10;
73 if (i % 10 == 0) {
74 if (torture_setting_bool(tctx, "progress", true)) {
75 torture_comment(tctx, "%d\r", i);
76 fflush(stdout);
79 asprintf(&fname, "\\torture.%u", n);
81 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
82 return False;
85 fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
86 if (fnum == -1) {
87 torture_comment(tctx, "open failed (%s)\n", smbcli_errstr(c->tree));
88 correct = False;
89 break;
92 if (smbcli_write(c->tree, fnum, 0, &pid, 0, sizeof(pid)) != sizeof(pid)) {
93 torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c->tree));
94 correct = False;
97 for (j=0;j<50;j++) {
98 if (smbcli_write(c->tree, fnum, 0, buf,
99 sizeof(pid)+(j*sizeof(buf)),
100 sizeof(buf)) != sizeof(buf)) {
101 torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c->tree));
102 correct = False;
106 pid2 = 0;
108 if (smbcli_read(c->tree, fnum, &pid2, 0, sizeof(pid)) != sizeof(pid)) {
109 torture_comment(tctx, "read failed (%s)\n", smbcli_errstr(c->tree));
110 correct = False;
113 if (pid2 != pid) {
114 torture_comment(tctx, "data corruption!\n");
115 correct = False;
118 if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
119 torture_comment(tctx, "close failed (%s)\n", smbcli_errstr(c->tree));
120 correct = False;
123 if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) {
124 torture_comment(tctx, "unlink failed (%s)\n", smbcli_errstr(c->tree));
125 correct = False;
128 if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
129 torture_comment(tctx, "unlock failed (%s)\n", smbcli_errstr(c->tree));
130 correct = False;
132 free(fname);
135 smbcli_close(c->tree, fnum2);
136 smbcli_unlink(c->tree, lockfname);
138 torture_comment(tctx, "%d\n", i);
140 return correct;
143 BOOL run_torture(struct torture_context *tctx, struct smbcli_state *cli, int dummy)
145 return rw_torture(tctx, cli);
150 see how many RPC pipes we can open at once
152 BOOL run_pipe_number(struct torture_context *tctx,
153 struct smbcli_state *cli1)
155 const char *pipe_name = "\\WKSSVC";
156 int fnum;
157 int num_pipes = 0;
159 while(1) {
160 fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
161 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
163 if (fnum == -1) {
164 torture_comment(tctx, "Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree));
165 break;
167 num_pipes++;
168 if (torture_setting_bool(tctx, "progress", true)) {
169 torture_comment(tctx, "%d\r", num_pipes);
170 fflush(stdout);
174 torture_comment(tctx, "pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
175 return True;
182 open N connections to the server and just hold them open
183 used for testing performance when there are N idle users
184 already connected
186 BOOL torture_holdcon(struct torture_context *tctx)
188 int i;
189 struct smbcli_state **cli;
190 int num_dead = 0;
192 torture_comment(tctx, "Opening %d connections\n", torture_numops);
194 cli = malloc_array_p(struct smbcli_state *, torture_numops);
196 for (i=0;i<torture_numops;i++) {
197 if (!torture_open_connection(&cli[i], i)) {
198 return False;
200 if (torture_setting_bool(tctx, "progress", true)) {
201 torture_comment(tctx, "opened %d connections\r", i);
202 fflush(stdout);
206 torture_comment(tctx, "\nStarting pings\n");
208 while (1) {
209 for (i=0;i<torture_numops;i++) {
210 NTSTATUS status;
211 if (cli[i]) {
212 status = smbcli_chkpath(cli[i]->tree, "\\");
213 if (!NT_STATUS_IS_OK(status)) {
214 torture_comment(tctx, "Connection %d is dead\n", i);
215 cli[i] = NULL;
216 num_dead++;
218 usleep(100);
222 if (num_dead == torture_numops) {
223 torture_comment(tctx, "All connections dead - finishing\n");
224 break;
227 torture_comment(tctx, ".");
228 fflush(stdout);
231 return True;
235 test how many open files this server supports on the one socket
237 BOOL run_maxfidtest(struct torture_context *tctx, struct smbcli_state *cli, int dummy)
239 #define MAXFID_TEMPLATE "\\maxfid\\fid%d\\maxfid.%d.%d"
240 char *fname;
241 int fnums[0x11000], i;
242 int retries=4, maxfid;
243 BOOL correct = True;
245 if (retries <= 0) {
246 torture_comment(tctx, "failed to connect\n");
247 return False;
250 if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
251 torture_comment(tctx, "Failed to deltree \\maxfid - %s\n",
252 smbcli_errstr(cli->tree));
253 return False;
255 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\maxfid"))) {
256 torture_comment(tctx, "Failed to mkdir \\maxfid, error=%s\n",
257 smbcli_errstr(cli->tree));
258 return False;
261 torture_comment(tctx, "Testing maximum number of open files\n");
263 for (i=0; i<0x11000; i++) {
264 if (i % 1000 == 0) {
265 asprintf(&fname, "\\maxfid\\fid%d", i/1000);
266 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) {
267 torture_comment(tctx, "Failed to mkdir %s, error=%s\n",
268 fname, smbcli_errstr(cli->tree));
269 return False;
271 free(fname);
273 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
274 if ((fnums[i] = smbcli_open(cli->tree, fname,
275 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
276 -1) {
277 torture_comment(tctx, "open of %s failed (%s)\n",
278 fname, smbcli_errstr(cli->tree));
279 torture_comment(tctx, "maximum fnum is %d\n", i);
280 break;
282 free(fname);
283 if (torture_setting_bool(tctx, "progress", true)) {
284 torture_comment(tctx, "%6d\r", i);
285 fflush(stdout);
288 torture_comment(tctx, "%6d\n", i);
289 i--;
291 maxfid = i;
293 torture_comment(tctx, "cleaning up\n");
294 for (i=0;i<maxfid/2;i++) {
295 asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
296 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) {
297 torture_comment(tctx, "Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree));
299 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
300 torture_comment(tctx, "unlink of %s failed (%s)\n",
301 fname, smbcli_errstr(cli->tree));
302 correct = False;
304 free(fname);
306 asprintf(&fname, MAXFID_TEMPLATE, (maxfid-i)/1000, maxfid-i,(int)getpid());
307 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[maxfid-i]))) {
308 torture_comment(tctx, "Close of fnum %d failed - %s\n", fnums[maxfid-i], smbcli_errstr(cli->tree));
310 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
311 torture_comment(tctx, "unlink of %s failed (%s)\n",
312 fname, smbcli_errstr(cli->tree));
313 correct = False;
315 free(fname);
317 if (torture_setting_bool(tctx, "progress", true)) {
318 torture_comment(tctx, "%6d %6d\r", i, maxfid-i);
319 fflush(stdout);
322 torture_comment(tctx, "%6d\n", 0);
324 if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
325 torture_comment(tctx, "Failed to deltree \\maxfid - %s\n",
326 smbcli_errstr(cli->tree));
327 return False;
330 torture_comment(tctx, "maxfid test finished\n");
331 if (!torture_close_connection(cli)) {
332 correct = False;
334 return correct;
335 #undef MAXFID_TEMPLATE
341 sees what IOCTLs are supported
343 BOOL torture_ioctl_test(struct torture_context *tctx,
344 struct smbcli_state *cli)
346 uint16_t device, function;
347 int fnum;
348 const char *fname = "\\ioctl.dat";
349 NTSTATUS status;
350 union smb_ioctl parms;
351 TALLOC_CTX *mem_ctx;
353 mem_ctx = talloc_named_const(tctx, 0, "ioctl_test");
355 smbcli_unlink(cli->tree, fname);
357 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
358 if (fnum == -1) {
359 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
360 return False;
363 parms.ioctl.level = RAW_IOCTL_IOCTL;
364 parms.ioctl.in.file.fnum = fnum;
365 parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
366 status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
367 torture_comment(tctx, "ioctl job info: %s\n", smbcli_errstr(cli->tree));
369 for (device=0;device<0x100;device++) {
370 torture_comment(tctx, "testing device=0x%x\n", device);
371 for (function=0;function<0x100;function++) {
372 parms.ioctl.in.request = (device << 16) | function;
373 status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
375 if (NT_STATUS_IS_OK(status)) {
376 torture_comment(tctx, "ioctl device=0x%x function=0x%x OK : %d bytes\n",
377 device, function, (int)parms.ioctl.out.blob.length);
382 return True;
385 static void benchrw_callback(struct smbcli_request *req);
386 enum benchrw_stage {
387 START,
388 OPEN_CONNECTION,
389 CLEANUP_TESTDIR,
390 MK_TESTDIR,
391 OPEN_FILE,
392 INITIAL_WRITE,
393 READ_WRITE_DATA,
394 MAX_OPS_REACHED,
395 ERROR,
396 CLOSE_FILE,
397 CLEANUP,
398 FINISHED
401 struct benchrw_state {
402 struct torture_context *tctx;
403 char *dname;
404 char *fname;
405 uint16_t fnum;
406 int nr;
407 struct smbcli_tree *cli;
408 uint8_t *buffer;
409 int writecnt;
410 int readcnt;
411 int completed;
412 int num_parallel_requests;
413 void *req_params;
414 enum benchrw_stage mode;
415 struct params{
416 struct unclist{
417 const char *host;
418 const char *share;
419 } **unc;
420 const char *workgroup;
421 int retry;
422 unsigned int writeblocks;
423 unsigned int blocksize;
424 unsigned int writeratio;
425 int num_parallel_requests;
426 } *lp_params;
430 init params using lp_parm_xxx
431 return number of unclist entries
433 static int init_benchrw_params(struct torture_context *tctx,
434 struct params *lpar)
436 char **unc_list = NULL;
437 int num_unc_names = 0, conn_index=0, empty_lines=0;
438 const char *p;
439 lpar->retry = torture_setting_int(tctx, "retry",3);
440 lpar->blocksize = torture_setting_int(tctx, "blocksize",65535);
441 lpar->writeblocks = torture_setting_int(tctx, "writeblocks",15);
442 lpar->writeratio = torture_setting_int(tctx, "writeratio",5);
443 lpar->num_parallel_requests = torture_setting_int(
444 tctx, "parallel_requests", 5);
445 lpar->workgroup = lp_workgroup();
447 p = torture_setting_string(tctx, "unclist", NULL);
448 if (p) {
449 char *h, *s;
450 unc_list = file_lines_load(p, &num_unc_names, NULL);
451 if (!unc_list || num_unc_names <= 0) {
452 torture_comment(tctx, "Failed to load unc names list "
453 "from '%s'\n", p);
454 exit(1);
457 lpar->unc = talloc_array(tctx, struct unclist *,
458 (num_unc_names-empty_lines));
459 for(conn_index = 0; conn_index < num_unc_names; conn_index++) {
460 /* ignore empty lines */
461 if(strlen(unc_list[conn_index % num_unc_names])==0){
462 empty_lines++;
463 continue;
465 if (!smbcli_parse_unc(
466 unc_list[conn_index % num_unc_names],
467 NULL, &h, &s)) {
468 torture_comment(
469 tctx, "Failed to parse UNC "
470 "name %s\n",
471 unc_list[conn_index % num_unc_names]);
472 exit(1);
474 lpar->unc[conn_index-empty_lines] =
475 talloc(tctx, struct unclist);
476 lpar->unc[conn_index-empty_lines]->host = h;
477 lpar->unc[conn_index-empty_lines]->share = s;
479 return num_unc_names-empty_lines;
480 }else{
481 lpar->unc = talloc_array(tctx, struct unclist *, 1);
482 lpar->unc[0] = talloc(tctx,struct unclist);
483 lpar->unc[0]->host = torture_setting_string(tctx, "host",
484 NULL);
485 lpar->unc[0]->share = torture_setting_string(tctx, "share",
486 NULL);
487 return 1;
492 Called when the reads & writes are finished. closes the file.
494 static NTSTATUS benchrw_close(struct torture_context *tctx,
495 struct smbcli_request *req,
496 struct benchrw_state *state)
498 union smb_close close_parms;
500 NT_STATUS_NOT_OK_RETURN(req->status);
502 torture_comment(tctx, "Close file %d (%d)\n",state->nr,state->fnum);
503 close_parms.close.level = RAW_CLOSE_CLOSE;
504 close_parms.close.in.file.fnum = state->fnum ;
505 close_parms.close.in.write_time = 0;
506 state->mode=CLOSE_FILE;
508 req = smb_raw_close_send(state->cli, &close_parms);
509 NT_STATUS_HAVE_NO_MEMORY(req);
510 /*register the callback function!*/
511 req->async.fn = benchrw_callback;
512 req->async.private = state;
514 return NT_STATUS_OK;
517 static NTSTATUS benchrw_readwrite(struct torture_context *tctx,
518 struct benchrw_state *state);
519 static void benchrw_callback(struct smbcli_request *req);
521 static void benchrw_rw_callback(struct smbcli_request *req)
523 struct benchrw_state *state = req->async.private;
524 struct torture_context *tctx = state->tctx;
526 if (!NT_STATUS_IS_OK(req->status)) {
527 state->mode = ERROR;
528 return;
531 state->completed++;
532 state->num_parallel_requests--;
534 if ((state->completed >= torture_numops)
535 && (state->num_parallel_requests == 0)) {
536 benchrw_callback(req);
537 talloc_free(req);
538 return;
541 talloc_free(req);
543 if (state->completed + state->num_parallel_requests
544 < torture_numops) {
545 benchrw_readwrite(tctx, state);
550 Called when the initial write is completed is done. write or read a file.
552 static NTSTATUS benchrw_readwrite(struct torture_context *tctx,
553 struct benchrw_state *state)
555 struct smbcli_request *req;
556 union smb_read rd;
557 union smb_write wr;
559 /* randomize between writes and reads*/
560 if ( random() % state->lp_params->writeratio == 0) {
561 torture_comment(tctx, "Callback WRITE file:%d (%d/%d)\n",
562 state->nr,state->completed,torture_numops);
563 wr.generic.level = RAW_WRITE_WRITEX ;
564 wr.writex.in.file.fnum = state->fnum ;
565 wr.writex.in.offset = 0;
566 wr.writex.in.wmode = 0 ;
567 wr.writex.in.remaining = 0;
568 wr.writex.in.count = state->lp_params->blocksize;
569 wr.writex.in.data = state->buffer;
570 state->readcnt=0;
571 req = smb_raw_write_send(state->cli,&wr);
573 else {
574 torture_comment(tctx,
575 "Callback READ file:%d (%d/%d) Offset:%d\n",
576 state->nr,state->completed,torture_numops,
577 (state->readcnt*state->lp_params->blocksize));
578 rd.generic.level = RAW_READ_READ;
579 rd.read.in.file.fnum = state->fnum ;
580 rd.read.in.offset = state->readcnt *
581 state->lp_params->blocksize;
582 rd.read.in.count = state->lp_params->blocksize;
583 rd.read.in.remaining = 0 ;
584 rd.read.out.data = state->buffer;
585 if(state->readcnt < state->lp_params->writeblocks){
586 state->readcnt++;
587 }else{
588 /*start reading from beginn of file*/
589 state->readcnt=0;
591 req = smb_raw_read_send(state->cli,&rd);
593 state->num_parallel_requests += 1;
594 NT_STATUS_HAVE_NO_MEMORY(req);
595 /*register the callback function!*/
596 req->async.fn = benchrw_rw_callback;
597 req->async.private = state;
599 return NT_STATUS_OK;
603 Called when the open is done. writes to the file.
605 static NTSTATUS benchrw_open(struct torture_context *tctx,
606 struct smbcli_request *req,
607 struct benchrw_state *state)
609 union smb_write wr;
610 if(state->mode == OPEN_FILE){
611 NTSTATUS status;
612 status = smb_raw_open_recv(req,tctx,(
613 union smb_open*)state->req_params);
614 NT_STATUS_NOT_OK_RETURN(status);
616 state->fnum = ((union smb_open*)state->req_params)
617 ->openx.out.file.fnum;
618 torture_comment(tctx, "File opened (%d)\n",state->fnum);
619 state->mode=INITIAL_WRITE;
622 torture_comment(tctx, "Write initial test file:%d (%d/%d)\n",state->nr,
623 (state->writecnt+1)*state->lp_params->blocksize,
624 (state->lp_params->writeblocks*state->lp_params->blocksize));
625 wr.generic.level = RAW_WRITE_WRITEX ;
626 wr.writex.in.file.fnum = state->fnum ;
627 wr.writex.in.offset = state->writecnt *
628 state->lp_params->blocksize;
629 wr.writex.in.wmode = 0 ;
630 wr.writex.in.remaining = (state->lp_params->writeblocks *
631 state->lp_params->blocksize)-
632 ((state->writecnt+1)*state->
633 lp_params->blocksize);
634 wr.writex.in.count = state->lp_params->blocksize;
635 wr.writex.in.data = state->buffer;
636 state->writecnt++;
637 if(state->writecnt == state->lp_params->writeblocks){
638 state->mode=READ_WRITE_DATA;
640 req = smb_raw_write_send(state->cli,&wr);
641 NT_STATUS_HAVE_NO_MEMORY(req);
643 /*register the callback function!*/
644 req->async.fn = benchrw_callback;
645 req->async.private = state;
646 return NT_STATUS_OK;
650 Called when the mkdir is done. Opens a file.
652 static NTSTATUS benchrw_mkdir(struct torture_context *tctx,
653 struct smbcli_request *req,
654 struct benchrw_state *state)
656 union smb_open *open_parms;
657 uint8_t *writedata;
659 NT_STATUS_NOT_OK_RETURN(req->status);
661 /* open/create the files */
662 torture_comment(tctx, "Open File %d/%d\n",state->nr+1,
663 lp_parm_int(-1, "torture", "nprocs", 4));
664 open_parms=talloc_zero(tctx, union smb_open);
665 NT_STATUS_HAVE_NO_MEMORY(open_parms);
666 open_parms->openx.level = RAW_OPEN_OPENX;
667 open_parms->openx.in.flags = 0;
668 open_parms->openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
669 open_parms->openx.in.search_attrs =
670 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
671 open_parms->openx.in.file_attrs = 0;
672 open_parms->openx.in.write_time = 0;
673 open_parms->openx.in.open_func = OPENX_OPEN_FUNC_CREATE;
674 open_parms->openx.in.size = 0;
675 open_parms->openx.in.timeout = 0;
676 open_parms->openx.in.fname = state->fname;
678 writedata = talloc_size(tctx,state->lp_params->blocksize);
679 NT_STATUS_HAVE_NO_MEMORY(writedata);
680 generate_random_buffer(writedata,state->lp_params->blocksize);
681 state->buffer=writedata;
682 state->writecnt=1;
683 state->readcnt=0;
684 state->req_params=open_parms;
685 state->mode=OPEN_FILE;
687 req = smb_raw_open_send(state->cli,open_parms);
688 NT_STATUS_HAVE_NO_MEMORY(req);
690 /*register the callback function!*/
691 req->async.fn = benchrw_callback;
692 req->async.private = state;
694 return NT_STATUS_OK;
698 handler for completion of a sub-request of the bench-rw test
700 static void benchrw_callback(struct smbcli_request *req)
702 struct benchrw_state *state = req->async.private;
703 struct torture_context *tctx = state->tctx;
705 /*dont send new requests when torture_numops is reached*/
706 if ((state->mode == READ_WRITE_DATA)
707 && (state->completed >= torture_numops)) {
708 state->mode=MAX_OPS_REACHED;
711 switch (state->mode) {
713 case MK_TESTDIR:
714 if (!NT_STATUS_IS_OK(benchrw_mkdir(tctx, req,state))) {
715 torture_comment(tctx, "Failed to create the test "
716 "directory - %s\n",
717 nt_errstr(req->status));
718 state->mode=ERROR;
719 return;
721 break;
722 case OPEN_FILE:
723 case INITIAL_WRITE:
724 if (!NT_STATUS_IS_OK(benchrw_open(tctx, req,state))){
725 torture_comment(tctx, "Failed to open/write the "
726 "file - %s\n",
727 nt_errstr(req->status));
728 state->mode=ERROR;
729 return;
731 break;
732 case READ_WRITE_DATA:
733 while (state->num_parallel_requests
734 < state->lp_params->num_parallel_requests) {
735 NTSTATUS status;
736 status = benchrw_readwrite(tctx,state);
737 if (!NT_STATUS_IS_OK(status)){
738 torture_comment(tctx, "Failed to read/write "
739 "the file - %s\n",
740 nt_errstr(req->status));
741 state->mode=ERROR;
742 return;
745 break;
746 case MAX_OPS_REACHED:
747 if (!NT_STATUS_IS_OK(benchrw_close(tctx,req,state))){
748 torture_comment(tctx, "Failed to read/write/close "
749 "the file - %s\n",
750 nt_errstr(req->status));
751 state->mode=ERROR;
752 return;
754 break;
755 case CLOSE_FILE:
756 torture_comment(tctx, "File %d closed\n",state->nr);
757 if (!NT_STATUS_IS_OK(req->status)) {
758 torture_comment(tctx, "Failed to close the "
759 "file - %s\n",
760 nt_errstr(req->status));
761 state->mode=ERROR;
762 return;
764 state->mode=CLEANUP;
765 return;
766 default:
767 break;
772 /* open connection async callback function*/
773 static void async_open_callback(struct composite_context *con)
775 struct benchrw_state *state = con->async.private_data;
776 struct torture_context *tctx = state->tctx;
777 int retry = state->lp_params->retry;
779 if (NT_STATUS_IS_OK(con->status)) {
780 state->cli=((struct smb_composite_connect*)
781 state->req_params)->out.tree;
782 state->mode=CLEANUP_TESTDIR;
783 }else{
784 if(state->writecnt < retry){
785 torture_comment(tctx, "Failed to open connection: "
786 "%d, Retry (%d/%d)\n",
787 state->nr,state->writecnt,retry);
788 state->writecnt++;
789 state->mode=START;
790 usleep(1000);
791 }else{
792 torture_comment(tctx, "Failed to open connection "
793 "(%d) - %s\n",
794 state->nr, nt_errstr(con->status));
795 state->mode=ERROR;
797 return;
802 establishs a smbcli_tree from scratch (async)
804 static struct composite_context *torture_connect_async(
805 struct torture_context *tctx,
806 struct smb_composite_connect *smb,
807 TALLOC_CTX *mem_ctx,
808 struct event_context *ev,
809 const char *host,
810 const char *share,
811 const char *workgroup)
813 torture_comment(tctx, "Open Connection to %s/%s\n",host,share);
814 smb->in.dest_host=talloc_strdup(mem_ctx,host);
815 smb->in.service=talloc_strdup(mem_ctx,share);
816 smb->in.port=0;
817 smb->in.called_name = strupper_talloc(mem_ctx, host);
818 smb->in.service_type=NULL;
819 smb->in.credentials=cmdline_credentials;
820 smb->in.fallback_to_anonymous=False;
821 smb->in.workgroup=workgroup;
823 return smb_composite_connect_send(smb,mem_ctx,ev);
826 BOOL run_benchrw(struct torture_context *tctx)
828 struct smb_composite_connect *smb_con;
829 const char *fname = "\\rwtest.dat";
830 struct smbcli_request *req;
831 struct benchrw_state **state;
832 int i , num_unc_names;
833 struct event_context *ev ;
834 struct composite_context *req1;
835 struct params lpparams;
836 union smb_mkdir parms;
837 int finished = 0;
838 BOOL success=True;
839 int torture_nprocs = lp_parm_int(-1, "torture", "nprocs", 4);
841 torture_comment(tctx, "Start BENCH-READWRITE num_ops=%d "
842 "num_nprocs=%d\n",
843 torture_numops, torture_nprocs);
845 /*init talloc context*/
846 ev = tctx->ev;
847 state = talloc_array(tctx, struct benchrw_state *, torture_nprocs);
849 /* init params using lp_parm_xxx */
850 num_unc_names = init_benchrw_params(tctx,&lpparams);
852 /* init private data structs*/
853 for(i = 0; i<torture_nprocs;i++){
854 state[i]=talloc(tctx,struct benchrw_state);
855 state[i]->tctx = tctx;
856 state[i]->completed=0;
857 state[i]->num_parallel_requests=0;
858 state[i]->lp_params=&lpparams;
859 state[i]->nr=i;
860 state[i]->dname=talloc_asprintf(tctx,"benchrw%d",i);
861 state[i]->fname=talloc_asprintf(tctx,"%s%s",
862 state[i]->dname,fname);
863 state[i]->mode=START;
864 state[i]->writecnt=0;
867 torture_comment(tctx, "Starting async requests\n");
868 while(finished != torture_nprocs){
869 finished=0;
870 for(i = 0; i<torture_nprocs;i++){
871 switch (state[i]->mode){
872 /*open multiple connections with the same userid */
873 case START:
874 smb_con = talloc(
875 tctx,struct smb_composite_connect) ;
876 state[i]->req_params=smb_con;
877 state[i]->mode=OPEN_CONNECTION;
878 req1 = torture_connect_async(
879 tctx, smb_con, tctx,ev,
880 lpparams.unc[i % num_unc_names]->host,
881 lpparams.unc[i % num_unc_names]->share,
882 lpparams.workgroup);
883 /* register callback fn + private data */
884 req1->async.fn = async_open_callback;
885 req1->async.private_data=state[i];
886 break;
887 /*setup test dirs (sync)*/
888 case CLEANUP_TESTDIR:
889 torture_comment(tctx, "Setup test dir %d\n",i);
890 smb_raw_exit(state[i]->cli->session);
891 if (smbcli_deltree(state[i]->cli,
892 state[i]->dname) == -1) {
893 torture_comment(
894 tctx,
895 "Unable to delete %s - %s\n",
896 state[i]->dname,
897 smbcli_errstr(state[i]->cli));
898 state[i]->mode=ERROR;
899 break;
901 state[i]->mode=MK_TESTDIR;
902 parms.mkdir.level = RAW_MKDIR_MKDIR;
903 parms.mkdir.in.path = state[i]->dname;
904 req = smb_raw_mkdir_send(state[i]->cli,&parms);
905 /* register callback fn + private data */
906 req->async.fn = benchrw_callback;
907 req->async.private=state[i];
908 break;
909 /* error occured , finish */
910 case ERROR:
911 finished++;
912 success=False;
913 break;
914 /* cleanup , close connection */
915 case CLEANUP:
916 torture_comment(tctx, "Deleting test dir %s "
917 "%d/%d\n",state[i]->dname,
918 i+1,torture_nprocs);
919 smbcli_deltree(state[i]->cli,state[i]->dname);
920 if (NT_STATUS_IS_ERR(smb_tree_disconnect(
921 state[i]->cli))) {
922 torture_comment(tctx, "ERROR: Tree "
923 "disconnect failed");
924 state[i]->mode=ERROR;
925 break;
927 state[i]->mode=FINISHED;
928 case FINISHED:
929 finished++;
930 break;
931 default:
932 event_loop_once(ev);
937 return success;