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 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.
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
;
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 uint_t n
= (uint_t
)random()%10;
74 if (torture_setting_bool(tctx
, "progress", true)) {
75 torture_comment(tctx
, "%d\r", i
);
79 asprintf(&fname
, "\\torture.%u", n
);
81 if (!wait_lock(c
, fnum2
, n
*sizeof(int), sizeof(int))) {
85 fnum
= smbcli_open(c
->tree
, fname
, O_RDWR
| O_CREAT
| O_TRUNC
, DENY_ALL
);
87 torture_comment(tctx
, "open failed (%s)\n", smbcli_errstr(c
->tree
));
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
));
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
));
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
));
114 torture_comment(tctx
, "data corruption!\n");
118 if (NT_STATUS_IS_ERR(smbcli_close(c
->tree
, fnum
))) {
119 torture_comment(tctx
, "close failed (%s)\n", smbcli_errstr(c
->tree
));
123 if (NT_STATUS_IS_ERR(smbcli_unlink(c
->tree
, fname
))) {
124 torture_comment(tctx
, "unlink failed (%s)\n", smbcli_errstr(c
->tree
));
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
));
135 smbcli_close(c
->tree
, fnum2
);
136 smbcli_unlink(c
->tree
, lockfname
);
138 torture_comment(tctx
, "%d\n", i
);
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";
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);
164 torture_comment(tctx
, "Open of pipe %s failed with error (%s)\n", pipe_name
, smbcli_errstr(cli1
->tree
));
168 if (torture_setting_bool(tctx
, "progress", true)) {
169 torture_comment(tctx
, "%d\r", num_pipes
);
174 torture_comment(tctx
, "pipe_number test - we can open %d %s pipes.\n", num_pipes
, pipe_name
);
182 open N connections to the server and just hold them open
183 used for testing performance when there are N idle users
186 BOOL
torture_holdcon(struct torture_context
*tctx
)
189 struct smbcli_state
**cli
;
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
)) {
200 if (torture_setting_bool(tctx
, "progress", true)) {
201 torture_comment(tctx
, "opened %d connections\r", i
);
206 torture_comment(tctx
, "\nStarting pings\n");
209 for (i
=0;i
<torture_numops
;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
);
222 if (num_dead
== torture_numops
) {
223 torture_comment(tctx
, "All connections dead - finishing\n");
227 torture_comment(tctx
, ".");
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"
241 int fnums
[0x11000], i
;
242 int retries
=4, maxfid
;
246 torture_comment(tctx
, "failed to connect\n");
250 if (smbcli_deltree(cli
->tree
, "\\maxfid") == -1) {
251 torture_comment(tctx
, "Failed to deltree \\maxfid - %s\n",
252 smbcli_errstr(cli
->tree
));
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
));
261 torture_comment(tctx
, "Testing maximum number of open files\n");
263 for (i
=0; i
<0x11000; i
++) {
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
));
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
)) ==
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
);
283 if (torture_setting_bool(tctx
, "progress", true)) {
284 torture_comment(tctx
, "%6d\r", i
);
288 torture_comment(tctx
, "%6d\n", 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
));
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
));
317 if (torture_setting_bool(tctx
, "progress", true)) {
318 torture_comment(tctx
, "%6d %6d\r", i
, maxfid
-i
);
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
));
330 torture_comment(tctx
, "maxfid test finished\n");
331 if (!torture_close_connection(cli
)) {
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
;
348 const char *fname
= "\\ioctl.dat";
350 union smb_ioctl parms
;
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
);
359 torture_comment(tctx
, "open of %s failed (%s)\n", fname
, smbcli_errstr(cli
->tree
));
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
);
385 static void benchrw_callback(struct smbcli_request
*req
);
401 struct benchrw_state
{
402 struct torture_context
*tctx
;
407 struct smbcli_tree
*cli
;
412 int num_parallel_requests
;
414 enum benchrw_stage mode
;
420 const char *workgroup
;
422 unsigned int writeblocks
;
423 unsigned int blocksize
;
424 unsigned int writeratio
;
425 int num_parallel_requests
;
430 init params using lp_parm_xxx
431 return number of unclist entries
433 static int init_benchrw_params(struct torture_context
*tctx
,
436 char **unc_list
= NULL
;
437 int num_unc_names
= 0, conn_index
=0, empty_lines
=0;
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
);
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 "
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){
465 if (!smbcli_parse_unc(
466 unc_list
[conn_index
% num_unc_names
],
469 tctx
, "Failed to parse UNC "
471 unc_list
[conn_index
% num_unc_names
]);
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
;
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",
485 lpar
->unc
[0]->share
= torture_setting_string(tctx
, "share",
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
;
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
)) {
532 state
->num_parallel_requests
--;
534 if ((state
->completed
>= torture_numops
)
535 && (state
->num_parallel_requests
== 0)) {
536 benchrw_callback(req
);
543 if (state
->completed
+ state
->num_parallel_requests
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
;
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
;
571 req
= smb_raw_write_send(state
->cli
,&wr
);
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
){
588 /*start reading from beginn of file*/
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
;
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
)
610 if(state
->mode
== OPEN_FILE
){
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
;
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
;
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
;
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
;
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
;
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
) {
714 if (!NT_STATUS_IS_OK(benchrw_mkdir(tctx
, req
,state
))) {
715 torture_comment(tctx
, "Failed to create the test "
717 nt_errstr(req
->status
));
724 if (!NT_STATUS_IS_OK(benchrw_open(tctx
, req
,state
))){
725 torture_comment(tctx
, "Failed to open/write the "
727 nt_errstr(req
->status
));
732 case READ_WRITE_DATA
:
733 while (state
->num_parallel_requests
734 < state
->lp_params
->num_parallel_requests
) {
736 status
= benchrw_readwrite(tctx
,state
);
737 if (!NT_STATUS_IS_OK(status
)){
738 torture_comment(tctx
, "Failed to read/write "
740 nt_errstr(req
->status
));
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 "
750 nt_errstr(req
->status
));
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 "
760 nt_errstr(req
->status
));
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
;
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
);
792 torture_comment(tctx
, "Failed to open connection "
794 state
->nr
, nt_errstr(con
->status
));
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
,
808 struct event_context
*ev
,
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
);
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
;
839 int torture_nprocs
= lp_parm_int(-1, "torture", "nprocs", 4);
841 torture_comment(tctx
, "Start BENCH-READWRITE num_ops=%d "
843 torture_numops
, torture_nprocs
);
845 /*init talloc context*/
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
;
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
){
870 for(i
= 0; i
<torture_nprocs
;i
++){
871 switch (state
[i
]->mode
){
872 /*open multiple connections with the same userid */
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
,
883 /* register callback fn + private data */
884 req1
->async
.fn
= async_open_callback
;
885 req1
->async
.private_data
=state
[i
];
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) {
895 "Unable to delete %s - %s\n",
897 smbcli_errstr(state
[i
]->cli
));
898 state
[i
]->mode
=ERROR
;
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
];
909 /* error occured , finish */
914 /* cleanup , close connection */
916 torture_comment(tctx
, "Deleting test dir %s "
917 "%d/%d\n",state
[i
]->dname
,
919 smbcli_deltree(state
[i
]->cli
,state
[i
]->dname
);
920 if (NT_STATUS_IS_ERR(smb_tree_disconnect(
922 torture_comment(tctx
, "ERROR: Tree "
923 "disconnect failed");
924 state
[i
]->mode
=ERROR
;
927 state
[i
]->mode
=FINISHED
;