2 Unix SMB/CIFS implementation.
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 3 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, see <http://www.gnu.org/licenses/>.
22 #include "lib/util/util_file.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/raw/raw_proto.h"
25 #include "system/time.h"
26 #include "system/wait.h"
27 #include "system/filesys.h"
28 #include "../libcli/smb/smb_constants.h"
29 #include "libcli/libcli.h"
30 #include "lib/events/events.h"
31 #include "libcli/resolve/resolve.h"
32 #include "torture/smbtorture.h"
33 #include "torture/util.h"
34 #include "libcli/smb_composite/smb_composite.h"
35 #include "libcli/composite/composite.h"
36 #include "param/param.h"
37 #include "torture/basic/proto.h"
38 #include "lib/cmdline/cmdline.h"
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;
49 static bool rw_torture(struct torture_context *tctx, struct smbcli_state *c)
51 const char *lockfname = "\\torture.lck";
55 pid_t pid2, pid = getpid();
60 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR | O_CREAT | O_EXCL,
63 fnum2 = smbcli_open(c->tree, lockfname, O_RDWR, DENY_NONE);
65 torture_comment(tctx, "open of %s failed (%s)\n", lockfname, smbcli_errstr(c->tree));
69 generate_random_buffer(buf, sizeof(buf));
71 for (i=0;i<torture_numops;i++) {
72 unsigned int n = (unsigned int)random()%10;
76 if (torture_setting_bool(tctx, "progress", true)) {
77 torture_comment(tctx, "%d\r", i);
81 ret = asprintf(&fname, "\\torture.%u", n);
82 torture_assert(tctx, ret != -1, "asprintf failed");
84 if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
88 fnum = smbcli_open(c->tree, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
90 torture_comment(tctx, "open failed (%s)\n", smbcli_errstr(c->tree));
95 if (smbcli_write(c->tree, fnum, 0, &pid, 0, sizeof(pid)) != sizeof(pid)) {
96 torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c->tree));
101 if (smbcli_write(c->tree, fnum, 0, buf,
102 sizeof(pid)+(j*sizeof(buf)),
103 sizeof(buf)) != sizeof(buf)) {
104 torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c->tree));
111 if (smbcli_read(c->tree, fnum, &pid2, 0, sizeof(pid)) != sizeof(pid)) {
112 torture_comment(tctx, "read failed (%s)\n", smbcli_errstr(c->tree));
117 torture_comment(tctx, "data corruption!\n");
121 if (NT_STATUS_IS_ERR(smbcli_close(c->tree, fnum))) {
122 torture_comment(tctx, "close failed (%s)\n", smbcli_errstr(c->tree));
126 if (NT_STATUS_IS_ERR(smbcli_unlink(c->tree, fname))) {
127 torture_comment(tctx, "unlink failed (%s)\n", smbcli_errstr(c->tree));
131 if (NT_STATUS_IS_ERR(smbcli_unlock(c->tree, fnum2, n*sizeof(int), sizeof(int)))) {
132 torture_comment(tctx, "unlock failed (%s)\n", smbcli_errstr(c->tree));
138 smbcli_close(c->tree, fnum2);
139 smbcli_unlink(c->tree, lockfname);
141 torture_comment(tctx, "%d\n", i);
146 bool run_torture(struct torture_context *tctx, struct smbcli_state *cli, int dummy)
148 return rw_torture(tctx, cli);
153 see how many RPC pipes we can open at once
155 bool run_pipe_number(struct torture_context *tctx,
156 struct smbcli_state *cli1)
158 const char *pipe_name = "\\WKSSVC";
163 fnum = smbcli_nt_create_full(cli1->tree, pipe_name, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
164 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE, NTCREATEX_DISP_OPEN_IF, 0, 0);
167 torture_comment(tctx, "Open of pipe %s failed with error (%s)\n", pipe_name, smbcli_errstr(cli1->tree));
171 if (torture_setting_bool(tctx, "progress", true)) {
172 torture_comment(tctx, "%d\r", num_pipes);
177 torture_comment(tctx, "pipe_number test - we can open %d %s pipes.\n", num_pipes, pipe_name );
185 open N connections to the server and just hold them open
186 used for testing performance when there are N idle users
189 bool torture_holdcon(struct torture_context *tctx)
192 struct smbcli_state **cli;
195 torture_comment(tctx, "Opening %d connections\n", torture_numops);
197 cli = malloc_array_p(struct smbcli_state *, torture_numops);
199 for (i=0;i<torture_numops;i++) {
200 if (!torture_open_connection(&cli[i], tctx, i)) {
203 if (torture_setting_bool(tctx, "progress", true)) {
204 torture_comment(tctx, "opened %d connections\r", i+1);
209 torture_comment(tctx, "\nStarting pings\n");
212 for (i=0;i<torture_numops;i++) {
215 status = smbcli_chkpath(cli[i]->tree, "\\");
216 if (!NT_STATUS_IS_OK(status)) {
217 torture_comment(tctx, "Connection %d is dead\n", i);
225 if (num_dead == torture_numops) {
226 torture_comment(tctx, "All connections dead - finishing\n");
230 torture_comment(tctx, ".");
238 open a file N times on the server and just hold them open
239 used for testing performance when there are N file handles
242 bool torture_holdopen(struct torture_context *tctx,
243 struct smbcli_state *cli)
246 const char *fname = "\\holdopen.dat";
249 smbcli_unlink(cli->tree, fname);
251 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
253 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
257 smbcli_close(cli->tree, fnum);
259 for (i=0;i<torture_numops;i++) {
262 op.generic.level = RAW_OPEN_NTCREATEX;
263 op.ntcreatex.in.root_fid.fnum = 0;
264 op.ntcreatex.in.flags = 0;
265 op.ntcreatex.in.access_mask = SEC_FILE_WRITE_DATA;
266 op.ntcreatex.in.create_options = 0;
267 op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
268 op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_MASK;
269 op.ntcreatex.in.alloc_size = 0;
270 op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
271 op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
272 op.ntcreatex.in.security_flags = 0;
273 op.ntcreatex.in.fname = fname;
274 status = smb_raw_open(cli->tree, tctx, &op);
275 if (!NT_STATUS_IS_OK(status)) {
276 torture_warning(tctx, "open %d failed\n", i);
280 if (torture_setting_bool(tctx, "progress", true)) {
281 torture_comment(tctx, "opened %d file\r", i);
286 torture_comment(tctx, "\nStarting pings\n");
291 status = smb_raw_echo(cli->transport, &ec);
292 torture_comment(tctx, ".");
299 test how many open files this server supports on the one socket
301 bool torture_maxfid_test(struct torture_context *tctx, struct smbcli_state *cli)
303 #define MAXFID_TEMPLATE "\\maxfid\\fid%d\\maxfid.%d.%d"
305 int fnums[0x11000], i;
306 int retries=4, maxfid;
311 torture_comment(tctx, "failed to connect\n");
315 if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
316 torture_comment(tctx, "Failed to deltree \\maxfid - %s\n",
317 smbcli_errstr(cli->tree));
320 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\maxfid"))) {
321 torture_comment(tctx, "Failed to mkdir \\maxfid, error=%s\n",
322 smbcli_errstr(cli->tree));
326 torture_comment(tctx, "Testing maximum number of open files\n");
328 for (i=0; i<0x11000; i++) {
330 ret = asprintf(&fname, "\\maxfid\\fid%d", i/1000);
331 torture_assert(tctx, ret != -1, "asprintf failed");
332 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, fname))) {
333 torture_comment(tctx, "Failed to mkdir %s, error=%s\n",
334 fname, smbcli_errstr(cli->tree));
339 ret = asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
340 torture_assert(tctx, ret != -1, "asprintf failed");
341 if ((fnums[i] = smbcli_open(cli->tree, fname,
342 O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) ==
344 torture_comment(tctx, "open of %s failed (%s)\n",
345 fname, smbcli_errstr(cli->tree));
346 torture_comment(tctx, "maximum fnum is %d\n", i);
350 if (torture_setting_bool(tctx, "progress", true)) {
351 torture_comment(tctx, "%6d\r", i);
355 torture_comment(tctx, "%6d\n", i);
359 torture_comment(tctx, "cleaning up\n");
360 for (i=0;i<maxfid;i++) {
361 ret = asprintf(&fname, MAXFID_TEMPLATE, i/1000, i,(int)getpid());
362 torture_assert(tctx, ret != -1, "asprintf failed");
363 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnums[i]))) {
364 torture_comment(tctx, "Close of fnum %d failed - %s\n", fnums[i], smbcli_errstr(cli->tree));
366 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
367 torture_comment(tctx, "unlink of %s failed (%s)\n",
368 fname, smbcli_errstr(cli->tree));
373 if (torture_setting_bool(tctx, "progress", true)) {
374 torture_comment(tctx, "%6d\r", i);
378 torture_comment(tctx, "%6d\n", 0);
380 if (smbcli_deltree(cli->tree, "\\maxfid") == -1) {
381 torture_comment(tctx, "Failed to deltree \\maxfid - %s\n",
382 smbcli_errstr(cli->tree));
386 torture_comment(tctx, "maxfid test finished\n");
389 #undef MAXFID_TEMPLATE
395 sees what IOCTLs are supported
397 bool torture_ioctl_test(struct torture_context *tctx,
398 struct smbcli_state *cli)
400 uint16_t device, function;
402 const char *fname = "\\ioctl.dat";
404 union smb_ioctl parms;
407 mem_ctx = talloc_named_const(tctx, 0, "ioctl_test");
409 smbcli_unlink(cli->tree, fname);
411 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
413 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
417 parms.ioctl.level = RAW_IOCTL_IOCTL;
418 parms.ioctl.in.file.fnum = fnum;
419 parms.ioctl.in.request = IOCTL_QUERY_JOB_INFO;
420 status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
421 torture_comment(tctx, "ioctl job info: %s\n", smbcli_errstr(cli->tree));
423 for (device=0;device<0x100;device++) {
424 torture_comment(tctx, "Testing device=0x%x\n", device);
425 for (function=0;function<0x100;function++) {
426 parms.ioctl.in.request = (device << 16) | function;
427 status = smb_raw_ioctl(cli->tree, mem_ctx, &parms);
429 if (NT_STATUS_IS_OK(status)) {
430 torture_comment(tctx, "ioctl device=0x%x function=0x%x OK : %d bytes\n",
431 device, function, (int)parms.ioctl.out.blob.length);
439 static void benchrw_callback(struct smbcli_request *req);
455 struct bench_params {
460 const char *workgroup;
462 unsigned int writeblocks;
463 unsigned int blocksize;
464 unsigned int writeratio;
465 int num_parallel_requests;
468 struct benchrw_state {
469 struct torture_context *tctx;
474 struct smbcli_tree *cli;
479 int num_parallel_requests;
481 enum benchrw_stage mode;
482 struct bench_params *lpcfg_params;
486 init params using lpcfg_parm_xxx
487 return number of unclist entries
489 static int init_benchrw_params(struct torture_context *tctx,
490 struct bench_params *lpar)
492 char **unc_list = NULL;
493 int num_unc_names = 0, conn_index=0, empty_lines=0;
495 lpar->retry = torture_setting_int(tctx, "retry",3);
496 lpar->blocksize = torture_setting_int(tctx, "blocksize",65535);
497 lpar->writeblocks = torture_setting_int(tctx, "writeblocks",15);
498 lpar->writeratio = torture_setting_int(tctx, "writeratio",5);
499 lpar->num_parallel_requests = torture_setting_int(
500 tctx, "parallel_requests", 5);
501 lpar->workgroup = lpcfg_workgroup(tctx->lp_ctx);
503 p = torture_setting_string(tctx, "unclist", NULL);
506 unc_list = file_lines_load(p, &num_unc_names, 0, NULL);
507 if (!unc_list || num_unc_names <= 0) {
508 torture_comment(tctx, "Failed to load unc names list "
513 lpar->unc = talloc_array(tctx, struct unclist *,
514 (num_unc_names-empty_lines));
515 for(conn_index = 0; conn_index < num_unc_names; conn_index++) {
516 /* ignore empty lines */
517 if(strlen(unc_list[conn_index % num_unc_names])==0){
521 if (!smbcli_parse_unc(
522 unc_list[conn_index % num_unc_names],
525 tctx, "Failed to parse UNC "
527 unc_list[conn_index % num_unc_names]);
530 lpar->unc[conn_index-empty_lines] =
531 talloc(tctx, struct unclist);
532 lpar->unc[conn_index-empty_lines]->host = h;
533 lpar->unc[conn_index-empty_lines]->share = s;
535 return num_unc_names-empty_lines;
537 lpar->unc = talloc_array(tctx, struct unclist *, 1);
538 lpar->unc[0] = talloc(tctx,struct unclist);
539 lpar->unc[0]->host = torture_setting_string(tctx, "host",
541 lpar->unc[0]->share = torture_setting_string(tctx, "share",
548 Called when the reads & writes are finished. closes the file.
550 static NTSTATUS benchrw_close(struct torture_context *tctx,
551 struct smbcli_request *req,
552 struct benchrw_state *state)
554 union smb_close close_parms;
556 NT_STATUS_NOT_OK_RETURN(req->status);
558 torture_comment(tctx, "Close file %d (%d)\n",state->nr,state->fnum);
559 close_parms.close.level = RAW_CLOSE_CLOSE;
560 close_parms.close.in.file.fnum = state->fnum ;
561 close_parms.close.in.write_time = 0;
562 state->mode=CLOSE_FILE;
564 req = smb_raw_close_send(state->cli, &close_parms);
565 NT_STATUS_HAVE_NO_MEMORY(req);
566 /*register the callback function!*/
567 req->async.fn = benchrw_callback;
568 req->async.private_data = state;
573 static NTSTATUS benchrw_readwrite(struct torture_context *tctx,
574 struct benchrw_state *state);
575 static void benchrw_callback(struct smbcli_request *req);
577 static void benchrw_rw_callback(struct smbcli_request *req)
579 struct benchrw_state *state = req->async.private_data;
580 struct torture_context *tctx = state->tctx;
582 if (!NT_STATUS_IS_OK(req->status)) {
588 state->num_parallel_requests--;
590 if ((state->completed >= torture_numops)
591 && (state->num_parallel_requests == 0)) {
592 benchrw_callback(req);
599 if (state->completed + state->num_parallel_requests
601 benchrw_readwrite(tctx, state);
606 Called when the initial write is completed is done. write or read a file.
608 static NTSTATUS benchrw_readwrite(struct torture_context *tctx,
609 struct benchrw_state *state)
611 struct smbcli_request *req;
615 /* randomize between writes and reads*/
616 if (random() % state->lpcfg_params->writeratio == 0) {
617 torture_comment(tctx, "Callback WRITE file:%d (%d/%d)\n",
618 state->nr,state->completed,torture_numops);
619 wr.generic.level = RAW_WRITE_WRITEX ;
620 wr.writex.in.file.fnum = state->fnum ;
621 wr.writex.in.offset = 0;
622 wr.writex.in.wmode = 0 ;
623 wr.writex.in.remaining = 0;
624 wr.writex.in.count = state->lpcfg_params->blocksize;
625 wr.writex.in.data = state->buffer;
627 req = smb_raw_write_send(state->cli,&wr);
630 torture_comment(tctx,
631 "Callback READ file:%d (%d/%d) Offset:%d\n",
632 state->nr,state->completed,torture_numops,
633 (state->readcnt*state->lpcfg_params->blocksize));
634 rd.generic.level = RAW_READ_READX;
635 rd.readx.in.file.fnum = state->fnum ;
636 rd.readx.in.offset = state->readcnt*state->lpcfg_params->blocksize;
637 rd.readx.in.mincnt = state->lpcfg_params->blocksize;
638 rd.readx.in.maxcnt = rd.readx.in.mincnt;
639 rd.readx.in.remaining = 0 ;
640 rd.readx.out.data = state->buffer;
641 rd.readx.in.read_for_execute = false;
642 if(state->readcnt < state->lpcfg_params->writeblocks){
645 /*start reading from beginning of file*/
648 req = smb_raw_read_send(state->cli,&rd);
650 state->num_parallel_requests += 1;
651 NT_STATUS_HAVE_NO_MEMORY(req);
652 /*register the callback function!*/
653 req->async.fn = benchrw_rw_callback;
654 req->async.private_data = state;
660 Called when the open is done. writes to the file.
662 static NTSTATUS benchrw_open(struct torture_context *tctx,
663 struct smbcli_request *req,
664 struct benchrw_state *state)
667 if(state->mode == OPEN_FILE){
669 status = smb_raw_open_recv(req,tctx,(
670 union smb_open*)state->req_params);
671 NT_STATUS_NOT_OK_RETURN(status);
673 state->fnum = ((union smb_open*)state->req_params)
674 ->openx.out.file.fnum;
675 torture_comment(tctx, "File opened (%d)\n",state->fnum);
676 state->mode=INITIAL_WRITE;
679 torture_comment(tctx, "Write initial test file:%d (%d/%d)\n",state->nr,
680 (state->writecnt+1)*state->lpcfg_params->blocksize,
681 (state->lpcfg_params->writeblocks*state->lpcfg_params->blocksize));
682 wr.generic.level = RAW_WRITE_WRITEX ;
683 wr.writex.in.file.fnum = state->fnum ;
684 wr.writex.in.offset = state->writecnt *
685 state->lpcfg_params->blocksize;
686 wr.writex.in.wmode = 0 ;
687 wr.writex.in.remaining = (state->lpcfg_params->writeblocks *
688 state->lpcfg_params->blocksize)-
689 ((state->writecnt+1)*state->
690 lpcfg_params->blocksize);
691 wr.writex.in.count = state->lpcfg_params->blocksize;
692 wr.writex.in.data = state->buffer;
694 if(state->writecnt == state->lpcfg_params->writeblocks){
695 state->mode=READ_WRITE_DATA;
697 req = smb_raw_write_send(state->cli,&wr);
698 NT_STATUS_HAVE_NO_MEMORY(req);
700 /*register the callback function!*/
701 req->async.fn = benchrw_callback;
702 req->async.private_data = state;
707 Called when the mkdir is done. Opens a file.
709 static NTSTATUS benchrw_mkdir(struct torture_context *tctx,
710 struct smbcli_request *req,
711 struct benchrw_state *state)
713 union smb_open *open_parms;
716 NT_STATUS_NOT_OK_RETURN(req->status);
718 /* open/create the files */
719 torture_comment(tctx, "Open File %d/%d\n",state->nr+1,
720 torture_setting_int(tctx, "nprocs", 4));
721 open_parms=talloc_zero(tctx, union smb_open);
722 NT_STATUS_HAVE_NO_MEMORY(open_parms);
723 open_parms->openx.level = RAW_OPEN_OPENX;
724 open_parms->openx.in.flags = 0;
725 open_parms->openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
726 open_parms->openx.in.search_attrs =
727 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
728 open_parms->openx.in.file_attrs = 0;
729 open_parms->openx.in.write_time = 0;
730 open_parms->openx.in.open_func = OPENX_OPEN_FUNC_CREATE;
731 open_parms->openx.in.size = 0;
732 open_parms->openx.in.timeout = 0;
733 open_parms->openx.in.fname = state->fname;
735 writedata = talloc_size(tctx,state->lpcfg_params->blocksize);
736 NT_STATUS_HAVE_NO_MEMORY(writedata);
737 generate_random_buffer(writedata,state->lpcfg_params->blocksize);
738 state->buffer=writedata;
741 state->req_params=open_parms;
742 state->mode=OPEN_FILE;
744 req = smb_raw_open_send(state->cli,open_parms);
745 NT_STATUS_HAVE_NO_MEMORY(req);
747 /*register the callback function!*/
748 req->async.fn = benchrw_callback;
749 req->async.private_data = state;
755 handler for completion of a sub-request of the bench-rw test
757 static void benchrw_callback(struct smbcli_request *req)
759 struct benchrw_state *state = req->async.private_data;
760 struct torture_context *tctx = state->tctx;
762 /*don't send new requests when torture_numops is reached*/
763 if ((state->mode == READ_WRITE_DATA)
764 && (state->completed >= torture_numops)) {
765 state->mode=MAX_OPS_REACHED;
768 switch (state->mode) {
771 if (!NT_STATUS_IS_OK(benchrw_mkdir(tctx, req,state))) {
772 torture_comment(tctx, "Failed to create the test "
774 nt_errstr(req->status));
781 if (!NT_STATUS_IS_OK(benchrw_open(tctx, req,state))){
782 torture_comment(tctx, "Failed to open/write the "
784 nt_errstr(req->status));
790 case READ_WRITE_DATA:
791 while (state->num_parallel_requests
792 < state->lpcfg_params->num_parallel_requests) {
794 status = benchrw_readwrite(tctx,state);
795 if (!NT_STATUS_IS_OK(status)){
796 torture_comment(tctx, "Failed to read/write "
798 nt_errstr(req->status));
804 case MAX_OPS_REACHED:
805 if (!NT_STATUS_IS_OK(benchrw_close(tctx,req,state))){
806 torture_comment(tctx, "Failed to read/write/close "
808 nt_errstr(req->status));
814 torture_comment(tctx, "File %d closed\n",state->nr);
815 if (!NT_STATUS_IS_OK(req->status)) {
816 torture_comment(tctx, "Failed to close the "
818 nt_errstr(req->status));
830 /* open connection async callback function*/
831 static void async_open_callback(struct composite_context *con)
833 struct benchrw_state *state = con->async.private_data;
834 struct torture_context *tctx = state->tctx;
835 int retry = state->lpcfg_params->retry;
837 if (NT_STATUS_IS_OK(con->status)) {
838 state->cli=((struct smb_composite_connect*)
839 state->req_params)->out.tree;
840 state->mode=CLEANUP_TESTDIR;
842 if(state->writecnt < retry){
843 torture_comment(tctx, "Failed to open connection: "
844 "%d, Retry (%d/%d)\n",
845 state->nr,state->writecnt,retry);
850 torture_comment(tctx, "Failed to open connection "
852 state->nr, nt_errstr(con->status));
860 establishes a smbcli_tree from scratch (async)
862 static struct composite_context *torture_connect_async(
863 struct torture_context *tctx,
864 struct smb_composite_connect *smb,
866 struct tevent_context *ev,
869 const char *workgroup)
871 torture_comment(tctx, "Open Connection to %s/%s\n",host,share);
872 smb->in.dest_host=talloc_strdup(mem_ctx,host);
873 smb->in.service=talloc_strdup(mem_ctx,share);
874 smb->in.dest_ports=lpcfg_smb_ports(tctx->lp_ctx);
875 smb->in.socket_options = lpcfg_socket_options(tctx->lp_ctx);
876 smb->in.called_name = strupper_talloc(mem_ctx, host);
877 smb->in.service_type=NULL;
878 smb->in.credentials = samba_cmdline_get_creds();
879 smb->in.fallback_to_anonymous=false;
880 smb->in.gensec_settings = lpcfg_gensec_settings(mem_ctx, tctx->lp_ctx);
881 smb->in.workgroup=workgroup;
882 lpcfg_smbcli_options(tctx->lp_ctx, &smb->in.options);
883 lpcfg_smbcli_session_options(tctx->lp_ctx, &smb->in.session_options);
885 return smb_composite_connect_send(smb,mem_ctx,
886 lpcfg_resolve_context(tctx->lp_ctx),ev);
889 bool run_benchrw(struct torture_context *tctx)
891 struct smb_composite_connect *smb_con;
892 const char *fname = "\\rwtest.dat";
893 struct smbcli_request *req;
894 struct benchrw_state **state;
895 int i , num_unc_names;
896 struct tevent_context *ev ;
897 struct composite_context *req1;
898 struct bench_params lpparams;
899 union smb_mkdir parms;
902 int torture_nprocs = torture_setting_int(tctx, "nprocs", 4);
904 torture_comment(tctx, "Start BENCH-READWRITE num_ops=%d "
906 torture_numops, torture_nprocs);
908 /*init talloc context*/
910 state = talloc_array(tctx, struct benchrw_state *, torture_nprocs);
912 /* init params using lpcfg_parm_xxx */
913 num_unc_names = init_benchrw_params(tctx,&lpparams);
915 /* init private data structs*/
916 for(i = 0; i<torture_nprocs;i++){
917 state[i]=talloc(tctx,struct benchrw_state);
918 state[i]->tctx = tctx;
919 state[i]->completed=0;
920 state[i]->num_parallel_requests=0;
921 state[i]->lpcfg_params=&lpparams;
923 state[i]->dname=talloc_asprintf(tctx,"benchrw%d",i);
924 state[i]->fname=talloc_asprintf(tctx,"%s%s",
925 state[i]->dname,fname);
926 state[i]->mode=START;
927 state[i]->writecnt=0;
930 torture_comment(tctx, "Starting async requests\n");
931 while(finished != torture_nprocs){
933 for(i = 0; i<torture_nprocs;i++){
934 switch (state[i]->mode){
935 /*open multiple connections with the same userid */
937 smb_con = talloc_zero(
938 tctx,struct smb_composite_connect);
939 state[i]->req_params=smb_con;
940 state[i]->mode=OPEN_CONNECTION;
941 req1 = torture_connect_async(
942 tctx, smb_con, tctx,ev,
943 lpparams.unc[i % num_unc_names]->host,
944 lpparams.unc[i % num_unc_names]->share,
946 /* register callback fn + private data */
947 req1->async.fn = async_open_callback;
948 req1->async.private_data=state[i];
950 /*setup test dirs (sync)*/
951 case CLEANUP_TESTDIR:
952 torture_comment(tctx, "Setup test dir %d\n",i);
953 smb_raw_exit(state[i]->cli->session);
954 if (smbcli_deltree(state[i]->cli,
955 state[i]->dname) == -1) {
958 "Unable to delete %s - %s\n",
960 smbcli_errstr(state[i]->cli));
961 state[i]->mode=ERROR;
964 state[i]->mode=MK_TESTDIR;
965 parms.mkdir.level = RAW_MKDIR_MKDIR;
966 parms.mkdir.in.path = state[i]->dname;
967 req = smb_raw_mkdir_send(state[i]->cli,&parms);
968 /* register callback fn + private data */
969 req->async.fn = benchrw_callback;
970 req->async.private_data=state[i];
972 /* error occurred , finish */
977 /* cleanup , close connection */
979 torture_comment(tctx, "Deleting test dir %s "
980 "%d/%d\n",state[i]->dname,
982 smbcli_deltree(state[i]->cli,state[i]->dname);
983 if (NT_STATUS_IS_ERR(smb_tree_disconnect(
985 torture_comment(tctx, "ERROR: Tree "
986 "disconnect failed");
987 state[i]->mode=ERROR;
990 state[i]->mode=FINISHED;
997 tevent_loop_once(ev);