2 Unix SMB/CIFS implementation.
6 Copyright (C) Stefan Metzmacher 2022
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "lib/param/param.h"
24 #include "libcli/smb2/smb2.h"
25 #include "libcli/smb2/smb2_calls.h"
26 #include "libcli/smb/smbXcli_base.h"
27 #include "torture/torture.h"
28 #include "torture/util.h"
29 #include "torture/smb2/proto.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "libcli/security/security.h"
33 #include "system/filesys.h"
34 #include "auth/credentials/credentials.h"
35 #include "lib/cmdline/cmdline.h"
36 #include "librpc/gen_ndr/security.h"
37 #include "lib/events/events.h"
39 #define FNAME "test_create.dat"
40 #define DNAME "smb2_open"
42 #define CHECK_STATUS(status, correct) do { \
43 if (!NT_STATUS_EQUAL(status, correct)) { \
44 torture_result(tctx, TORTURE_FAIL, \
45 "(%s) Incorrect status %s - should be %s\n", \
46 __location__, nt_errstr(status), nt_errstr(correct)); \
50 #define CHECK_EQUAL(v, correct) do { \
52 torture_result(tctx, TORTURE_FAIL, \
53 "(%s) Incorrect value for %s 0x%08llx - " \
54 "should be 0x%08llx\n", \
56 (unsigned long long)v, \
57 (unsigned long long)correct); \
61 #define CHECK_TIME(t, field) do { \
63 finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
64 finfo.all_info.in.file.handle = h1; \
65 status = smb2_getinfo_file(tree, tctx, &finfo); \
66 CHECK_STATUS(status, NT_STATUS_OK); \
68 t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \
69 if (abs(t1-t2) > 2) { \
70 torture_result(tctx, TORTURE_FAIL, \
71 "(%s) wrong time for field %s %s - %s\n", \
72 __location__, #field, \
73 timestring(tctx, t1), \
74 timestring(tctx, t2)); \
75 dump_all_info(tctx, &finfo); \
79 #define CHECK_NTTIME(t, field) do { \
81 finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
82 finfo.all_info.in.file.handle = h1; \
83 status = smb2_getinfo_file(tree, tctx, &finfo); \
84 CHECK_STATUS(status, NT_STATUS_OK); \
85 t2 = finfo.all_info.out.field; \
86 if (llabs((int64_t)(t-t2)) > 20000) { \
87 torture_result(tctx, TORTURE_FAIL, \
88 "(%s) wrong time for field %s %s - %s\n", \
89 __location__, #field, \
90 nt_time_string(tctx, t), \
91 nt_time_string(tctx, t2)); \
92 dump_all_info(tctx, &finfo); \
96 #define CHECK_ALL_INFO(v, field) do { \
97 finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
98 finfo.all_info.in.file.handle = h1; \
99 status = smb2_getinfo_file(tree, tctx, &finfo); \
100 CHECK_STATUS(status, NT_STATUS_OK); \
101 if ((v) != (finfo.all_info.out.field)) { \
102 torture_result(tctx, TORTURE_FAIL, \
103 "(%s) wrong value for field %s 0x%x - 0x%x\n", \
104 __location__, #field, (int)v,\
105 (int)(finfo.all_info.out.field)); \
106 dump_all_info(tctx, &finfo); \
110 #define CHECK_VAL(v, correct) do { \
111 if ((v) != (correct)) { \
112 torture_result(tctx, TORTURE_FAIL, \
113 "(%s) wrong value for %s 0x%x - should be 0x%x\n", \
114 __location__, #v, (int)(v), (int)correct); \
118 #define SET_ATTRIB(sattrib) do { \
119 union smb_setfileinfo sfinfo; \
120 ZERO_STRUCT(sfinfo.basic_info.in); \
121 sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION; \
122 sfinfo.basic_info.in.file.handle = h1; \
123 sfinfo.basic_info.in.attrib = sattrib; \
124 status = smb2_setinfo_file(tree, &sfinfo); \
125 if (!NT_STATUS_IS_OK(status)) { \
126 torture_comment(tctx, \
127 "(%s) Failed to set attrib 0x%x on %s\n", \
128 __location__, (unsigned int)(sattrib), fname); \
132 stress testing keepalive iops
135 struct test_smb2_bench_echo_conn
;
136 struct test_smb2_bench_echo_loop
;
138 struct test_smb2_bench_echo_state
{
139 struct torture_context
*tctx
;
141 struct test_smb2_bench_echo_conn
*conns
;
143 struct test_smb2_bench_echo_loop
*loops
;
144 size_t pending_loops
;
145 struct timeval starttime
;
148 uint64_t num_finished
;
149 double total_latency
;
156 struct test_smb2_bench_echo_conn
{
157 struct test_smb2_bench_echo_state
*state
;
159 struct smb2_tree
*tree
;
162 struct test_smb2_bench_echo_loop
{
163 struct test_smb2_bench_echo_state
*state
;
164 struct test_smb2_bench_echo_conn
*conn
;
166 struct tevent_immediate
*im
;
167 struct tevent_req
*req
;
168 struct timeval starttime
;
169 uint64_t num_started
;
170 uint64_t num_finished
;
171 uint64_t total_finished
;
172 uint64_t max_finished
;
173 double total_latency
;
179 static void test_smb2_bench_echo_loop_do(
180 struct test_smb2_bench_echo_loop
*loop
);
182 static void test_smb2_bench_echo_loop_start(struct tevent_context
*ctx
,
183 struct tevent_immediate
*im
,
186 struct test_smb2_bench_echo_loop
*loop
=
187 (struct test_smb2_bench_echo_loop
*)
190 test_smb2_bench_echo_loop_do(loop
);
193 static void test_smb2_bench_echo_loop_done(struct tevent_req
*req
);
195 static void test_smb2_bench_echo_loop_do(
196 struct test_smb2_bench_echo_loop
*loop
)
198 struct test_smb2_bench_echo_state
*state
= loop
->state
;
200 loop
->num_started
+= 1;
201 loop
->starttime
= timeval_current();
202 loop
->req
= smb2cli_echo_send(state
->loops
,
204 loop
->conn
->tree
->session
->transport
->conn
,
206 torture_assert_goto(state
->tctx
, loop
->req
!= NULL
,
207 state
->ok
, asserted
, "smb2cli_echo_send");
209 tevent_req_set_callback(loop
->req
,
210 test_smb2_bench_echo_loop_done
,
217 static void test_smb2_bench_echo_loop_done(struct tevent_req
*req
)
219 struct test_smb2_bench_echo_loop
*loop
=
220 (struct test_smb2_bench_echo_loop
*)
221 _tevent_req_callback_data(req
);
222 struct test_smb2_bench_echo_state
*state
= loop
->state
;
223 double latency
= timeval_elapsed(&loop
->starttime
);
224 TALLOC_CTX
*frame
= talloc_stackframe();
226 torture_assert_goto(state
->tctx
, loop
->req
== req
,
227 state
->ok
, asserted
, __location__
);
228 loop
->error
= smb2cli_echo_recv(req
);
229 torture_assert_ntstatus_ok_goto(state
->tctx
, loop
->error
,
230 state
->ok
, asserted
, __location__
);
231 SMB_ASSERT(latency
>= 0.000001);
233 if (loop
->num_finished
== 0) {
235 loop
->min_latency
= latency
;
236 loop
->max_latency
= latency
;
239 loop
->num_finished
+= 1;
240 loop
->total_finished
+= 1;
241 loop
->total_latency
+= latency
;
243 if (latency
< loop
->min_latency
) {
244 loop
->min_latency
= latency
;
247 if (latency
> loop
->max_latency
) {
248 loop
->max_latency
= latency
;
251 if (loop
->total_finished
>= loop
->max_finished
) {
252 if (state
->pending_loops
> 0) {
253 state
->pending_loops
-= 1;
255 if (state
->pending_loops
== 0) {
261 test_smb2_bench_echo_loop_do(loop
);
268 static void test_smb2_bench_echo_progress(struct tevent_context
*ev
,
269 struct tevent_timer
*te
,
270 struct timeval current_time
,
273 struct test_smb2_bench_echo_state
*state
=
274 (struct test_smb2_bench_echo_state
*)private_data
;
275 uint64_t num_echos
= 0;
276 double total_echo_latency
= 0;
277 double min_echo_latency
= 0;
278 double max_echo_latency
= 0;
279 double avs_echo_latency
= 0;
282 state
->timecount
+= 1;
284 for (i
=0;i
<state
->num_loops
;i
++) {
285 struct test_smb2_bench_echo_loop
*loop
=
288 num_echos
+= loop
->num_finished
;
289 total_echo_latency
+= loop
->total_latency
;
290 if (min_echo_latency
== 0.0 && loop
->min_latency
!= 0.0) {
291 min_echo_latency
= loop
->min_latency
;
293 if (loop
->min_latency
< min_echo_latency
) {
294 min_echo_latency
= loop
->min_latency
;
296 if (max_echo_latency
== 0.0) {
297 max_echo_latency
= loop
->max_latency
;
299 if (loop
->max_latency
> max_echo_latency
) {
300 max_echo_latency
= loop
->max_latency
;
302 loop
->num_finished
= 0;
303 loop
->total_latency
= 0.0;
306 state
->num_finished
+= num_echos
;
307 state
->total_latency
+= total_echo_latency
;
308 if (state
->min_latency
== 0.0 && min_echo_latency
!= 0.0) {
309 state
->min_latency
= min_echo_latency
;
311 if (min_echo_latency
< state
->min_latency
) {
312 state
->min_latency
= min_echo_latency
;
314 if (state
->max_latency
== 0.0) {
315 state
->max_latency
= max_echo_latency
;
317 if (max_echo_latency
> state
->max_latency
) {
318 state
->max_latency
= max_echo_latency
;
321 if (state
->timecount
< state
->timelimit
) {
322 te
= tevent_add_timer(state
->tctx
->ev
,
324 timeval_current_ofs(1, 0),
325 test_smb2_bench_echo_progress
,
327 torture_assert_goto(state
->tctx
, te
!= NULL
,
328 state
->ok
, asserted
, "tevent_add_timer");
330 if (!torture_setting_bool(state
->tctx
, "progress", true)) {
334 avs_echo_latency
= total_echo_latency
/ num_echos
;
336 torture_comment(state
->tctx
,
338 "echo[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f] \r",
339 timeval_elapsed(&state
->starttime
),
340 (unsigned long long)num_echos
,
347 avs_echo_latency
= state
->total_latency
/ state
->num_finished
;
348 num_echos
= state
->num_finished
/ state
->timelimit
;
350 torture_comment(state
->tctx
,
352 "echo[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f]\n",
353 timeval_elapsed(&state
->starttime
),
354 (unsigned long long)num_echos
,
363 static bool test_smb2_bench_echo(struct torture_context
*tctx
,
364 struct smb2_tree
*tree
)
366 struct test_smb2_bench_echo_state
*state
= NULL
;
368 int torture_nprocs
= torture_setting_int(tctx
, "nprocs", 4);
369 int torture_qdepth
= torture_setting_int(tctx
, "qdepth", 1);
372 int looplimit
= torture_setting_int(tctx
, "looplimit", -1);
373 int timelimit
= torture_setting_int(tctx
, "timelimit", 10);
374 struct tevent_timer
*te
= NULL
;
375 uint32_t timeout_msec
;
377 state
= talloc_zero(tctx
, struct test_smb2_bench_echo_state
);
378 torture_assert(tctx
, state
!= NULL
, __location__
);
380 state
->num_conns
= torture_nprocs
;
381 state
->conns
= talloc_zero_array(state
,
382 struct test_smb2_bench_echo_conn
,
384 torture_assert(tctx
, state
->conns
!= NULL
, __location__
);
385 state
->num_loops
= torture_nprocs
* torture_qdepth
;
386 state
->loops
= talloc_zero_array(state
,
387 struct test_smb2_bench_echo_loop
,
389 torture_assert(tctx
, state
->loops
!= NULL
, __location__
);
391 state
->timelimit
= MAX(timelimit
, 1);
393 timeout_msec
= tree
->session
->transport
->options
.request_timeout
* 1000;
395 torture_comment(tctx
, "Opening %zu connections\n", state
->num_conns
);
397 for (i
=0;i
<state
->num_conns
;i
++) {
398 struct smb2_tree
*ct
= NULL
;
399 DATA_BLOB out_input_buffer
= data_blob_null
;
400 DATA_BLOB out_output_buffer
= data_blob_null
;
403 state
->conns
[i
].state
= state
;
404 state
->conns
[i
].idx
= i
;
406 if (!torture_smb2_connection(tctx
, &ct
)) {
407 torture_comment(tctx
, "Failed opening %zu/%zu connections\n", i
, state
->num_conns
);
410 state
->conns
[i
].tree
= talloc_steal(state
->conns
, ct
);
412 smb2cli_conn_set_max_credits(ct
->session
->transport
->conn
, 8192);
413 smb2cli_ioctl(ct
->session
->transport
->conn
,
415 ct
->session
->smbXcli
,
417 UINT64_MAX
, /* in_fid_persistent */
418 UINT64_MAX
, /* in_fid_volatile */
420 0, /* in_max_input_length */
421 NULL
, /* in_input_buffer */
422 1, /* in_max_output_length */
423 NULL
, /* in_output_buffer */
424 SMB2_IOCTL_FLAG_IS_FSCTL
,
429 smbXcli_conn_is_connected(ct
->session
->transport
->conn
),
430 "smbXcli_conn_is_connected");
432 for (pcli
= 0; pcli
< torture_qdepth
; pcli
++) {
433 struct test_smb2_bench_echo_loop
*loop
= &state
->loops
[li
];
436 if (looplimit
!= -1) {
437 loop
->max_finished
= looplimit
;
439 loop
->max_finished
= UINT64_MAX
;
442 loop
->conn
= &state
->conns
[i
];
443 loop
->im
= tevent_create_immediate(state
->loops
);
444 torture_assert(tctx
, loop
->im
!= NULL
, __location__
);
446 tevent_schedule_immediate(loop
->im
,
448 test_smb2_bench_echo_loop_start
,
453 torture_comment(tctx
, "Opened %zu connections with qdepth=%d => %zu loops\n",
454 state
->num_conns
, torture_qdepth
, state
->num_loops
);
456 torture_comment(tctx
, "Running for %d seconds\n", state
->timelimit
);
458 state
->starttime
= timeval_current();
459 state
->pending_loops
= state
->num_loops
;
461 te
= tevent_add_timer(tctx
->ev
,
463 timeval_current_ofs(1, 0),
464 test_smb2_bench_echo_progress
,
466 torture_assert(tctx
, te
!= NULL
, __location__
);
468 while (!state
->stop
) {
469 int rc
= tevent_loop_once(tctx
->ev
);
470 torture_assert_int_equal(tctx
, rc
, 0, "tevent_loop_once");
473 torture_comment(tctx
, "%.2f seconds\n", timeval_elapsed(&state
->starttime
));
479 stress testing path base operations
480 e.g. contention on lockting.tdb records
483 struct test_smb2_bench_path_contention_shared_conn
;
484 struct test_smb2_bench_path_contention_shared_loop
;
486 struct test_smb2_bench_path_contention_shared_state
{
487 struct torture_context
*tctx
;
489 struct test_smb2_bench_path_contention_shared_conn
*conns
;
491 struct test_smb2_bench_path_contention_shared_loop
*loops
;
492 struct timeval starttime
;
496 uint64_t num_finished
;
497 double total_latency
;
502 uint64_t num_finished
;
503 double total_latency
;
511 struct test_smb2_bench_path_contention_shared_conn
{
512 struct test_smb2_bench_path_contention_shared_state
*state
;
514 struct smb2_tree
*tree
;
517 struct test_smb2_bench_path_contention_shared_loop
{
518 struct test_smb2_bench_path_contention_shared_state
*state
;
519 struct test_smb2_bench_path_contention_shared_conn
*conn
;
521 struct tevent_immediate
*im
;
523 struct smb2_create io
;
524 struct smb2_request
*req
;
525 struct timeval starttime
;
526 uint64_t num_started
;
527 uint64_t num_finished
;
528 double total_latency
;
533 struct smb2_close io
;
534 struct smb2_request
*req
;
535 struct timeval starttime
;
536 uint64_t num_started
;
537 uint64_t num_finished
;
538 double total_latency
;
545 static void test_smb2_bench_path_contention_loop_open(
546 struct test_smb2_bench_path_contention_shared_loop
*loop
);
548 static void test_smb2_bench_path_contention_loop_start(struct tevent_context
*ctx
,
549 struct tevent_immediate
*im
,
552 struct test_smb2_bench_path_contention_shared_loop
*loop
=
553 (struct test_smb2_bench_path_contention_shared_loop
*)
556 test_smb2_bench_path_contention_loop_open(loop
);
559 static void test_smb2_bench_path_contention_loop_opened(struct smb2_request
*req
);
561 static void test_smb2_bench_path_contention_loop_open(
562 struct test_smb2_bench_path_contention_shared_loop
*loop
)
564 struct test_smb2_bench_path_contention_shared_state
*state
= loop
->state
;
566 loop
->opens
.num_started
+= 1;
567 loop
->opens
.starttime
= timeval_current();
568 loop
->opens
.req
= smb2_create_send(loop
->conn
->tree
, &loop
->opens
.io
);
569 torture_assert_goto(state
->tctx
, loop
->opens
.req
!= NULL
,
570 state
->ok
, asserted
, "smb2_create_send");
572 loop
->opens
.req
->async
.fn
= test_smb2_bench_path_contention_loop_opened
;
573 loop
->opens
.req
->async
.private_data
= loop
;
579 static void test_smb2_bench_path_contention_loop_close(
580 struct test_smb2_bench_path_contention_shared_loop
*loop
);
582 static void test_smb2_bench_path_contention_loop_opened(struct smb2_request
*req
)
584 struct test_smb2_bench_path_contention_shared_loop
*loop
=
585 (struct test_smb2_bench_path_contention_shared_loop
*)
586 req
->async
.private_data
;
587 struct test_smb2_bench_path_contention_shared_state
*state
= loop
->state
;
588 double latency
= timeval_elapsed(&loop
->opens
.starttime
);
589 TALLOC_CTX
*frame
= talloc_stackframe();
591 torture_assert_goto(state
->tctx
, loop
->opens
.req
== req
,
592 state
->ok
, asserted
, __location__
);
593 loop
->error
= smb2_create_recv(req
, frame
, &loop
->opens
.io
);
594 torture_assert_ntstatus_ok_goto(state
->tctx
, loop
->error
,
595 state
->ok
, asserted
, __location__
);
596 ZERO_STRUCT(loop
->opens
.io
.out
.blobs
);
597 SMB_ASSERT(latency
>= 0.000001);
599 if (loop
->opens
.num_finished
== 0) {
601 loop
->opens
.min_latency
= latency
;
602 loop
->opens
.max_latency
= latency
;
605 loop
->opens
.num_finished
+= 1;
606 loop
->opens
.total_latency
+= latency
;
608 if (latency
< loop
->opens
.min_latency
) {
609 loop
->opens
.min_latency
= latency
;
612 if (latency
> loop
->opens
.max_latency
) {
613 loop
->opens
.max_latency
= latency
;
617 test_smb2_bench_path_contention_loop_close(loop
);
624 static void test_smb2_bench_path_contention_loop_closed(struct smb2_request
*req
);
626 static void test_smb2_bench_path_contention_loop_close(
627 struct test_smb2_bench_path_contention_shared_loop
*loop
)
629 struct test_smb2_bench_path_contention_shared_state
*state
= loop
->state
;
631 loop
->closes
.num_started
+= 1;
632 loop
->closes
.starttime
= timeval_current();
633 loop
->closes
.io
.in
.file
= loop
->opens
.io
.out
.file
;
634 loop
->closes
.req
= smb2_close_send(loop
->conn
->tree
, &loop
->closes
.io
);
635 torture_assert_goto(state
->tctx
, loop
->closes
.req
!= NULL
,
636 state
->ok
, asserted
, "smb2_close_send");
638 loop
->closes
.req
->async
.fn
= test_smb2_bench_path_contention_loop_closed
;
639 loop
->closes
.req
->async
.private_data
= loop
;
645 static void test_smb2_bench_path_contention_loop_closed(struct smb2_request
*req
)
647 struct test_smb2_bench_path_contention_shared_loop
*loop
=
648 (struct test_smb2_bench_path_contention_shared_loop
*)
649 req
->async
.private_data
;
650 struct test_smb2_bench_path_contention_shared_state
*state
= loop
->state
;
651 double latency
= timeval_elapsed(&loop
->closes
.starttime
);
653 torture_assert_goto(state
->tctx
, loop
->closes
.req
== req
,
654 state
->ok
, asserted
, __location__
);
655 loop
->error
= smb2_close_recv(req
, &loop
->closes
.io
);
656 torture_assert_ntstatus_ok_goto(state
->tctx
, loop
->error
,
657 state
->ok
, asserted
, __location__
);
658 SMB_ASSERT(latency
>= 0.000001);
659 if (loop
->closes
.num_finished
== 0) {
661 loop
->closes
.min_latency
= latency
;
662 loop
->closes
.max_latency
= latency
;
664 loop
->closes
.num_finished
+= 1;
666 loop
->closes
.total_latency
+= latency
;
668 if (latency
< loop
->closes
.min_latency
) {
669 loop
->closes
.min_latency
= latency
;
672 if (latency
> loop
->closes
.max_latency
) {
673 loop
->closes
.max_latency
= latency
;
676 test_smb2_bench_path_contention_loop_open(loop
);
682 static void test_smb2_bench_path_contention_progress(struct tevent_context
*ev
,
683 struct tevent_timer
*te
,
684 struct timeval current_time
,
687 struct test_smb2_bench_path_contention_shared_state
*state
=
688 (struct test_smb2_bench_path_contention_shared_state
*)private_data
;
689 uint64_t num_opens
= 0;
690 double total_open_latency
= 0;
691 double min_open_latency
= 0;
692 double max_open_latency
= 0;
693 double avs_open_latency
= 0;
694 uint64_t num_closes
= 0;
695 double total_close_latency
= 0;
696 double min_close_latency
= 0;
697 double max_close_latency
= 0;
698 double avs_close_latency
= 0;
701 state
->timecount
+= 1;
703 for (i
=0;i
<state
->num_loops
;i
++) {
704 struct test_smb2_bench_path_contention_shared_loop
*loop
=
707 num_opens
+= loop
->opens
.num_finished
;
708 total_open_latency
+= loop
->opens
.total_latency
;
709 if (min_open_latency
== 0.0 && loop
->opens
.min_latency
!= 0.0) {
710 min_open_latency
= loop
->opens
.min_latency
;
712 if (loop
->opens
.min_latency
< min_open_latency
) {
713 min_open_latency
= loop
->opens
.min_latency
;
715 if (max_open_latency
== 0.0) {
716 max_open_latency
= loop
->opens
.max_latency
;
718 if (loop
->opens
.max_latency
> max_open_latency
) {
719 max_open_latency
= loop
->opens
.max_latency
;
721 loop
->opens
.num_finished
= 0;
722 loop
->opens
.total_latency
= 0.0;
724 num_closes
+= loop
->closes
.num_finished
;
725 total_close_latency
+= loop
->closes
.total_latency
;
726 if (min_close_latency
== 0.0 && loop
->closes
.min_latency
!= 0.0) {
727 min_close_latency
= loop
->closes
.min_latency
;
729 if (loop
->closes
.min_latency
< min_close_latency
) {
730 min_close_latency
= loop
->closes
.min_latency
;
732 if (max_close_latency
== 0.0) {
733 max_close_latency
= loop
->closes
.max_latency
;
735 if (loop
->closes
.max_latency
> max_close_latency
) {
736 max_close_latency
= loop
->closes
.max_latency
;
738 loop
->closes
.num_finished
= 0;
739 loop
->closes
.total_latency
= 0.0;
742 state
->opens
.num_finished
+= num_opens
;
743 state
->opens
.total_latency
+= total_open_latency
;
744 if (state
->opens
.min_latency
== 0.0 && min_open_latency
!= 0.0) {
745 state
->opens
.min_latency
= min_open_latency
;
747 if (min_open_latency
< state
->opens
.min_latency
) {
748 state
->opens
.min_latency
= min_open_latency
;
750 if (state
->opens
.max_latency
== 0.0) {
751 state
->opens
.max_latency
= max_open_latency
;
753 if (max_open_latency
> state
->opens
.max_latency
) {
754 state
->opens
.max_latency
= max_open_latency
;
757 state
->closes
.num_finished
+= num_closes
;
758 state
->closes
.total_latency
+= total_close_latency
;
759 if (state
->closes
.min_latency
== 0.0 && min_close_latency
!= 0.0) {
760 state
->closes
.min_latency
= min_close_latency
;
762 if (min_close_latency
< state
->closes
.min_latency
) {
763 state
->closes
.min_latency
= min_close_latency
;
765 if (state
->closes
.max_latency
== 0.0) {
766 state
->closes
.max_latency
= max_close_latency
;
768 if (max_close_latency
> state
->closes
.max_latency
) {
769 state
->closes
.max_latency
= max_close_latency
;
772 if (state
->timecount
< state
->timelimit
) {
773 te
= tevent_add_timer(state
->tctx
->ev
,
775 timeval_current_ofs(1, 0),
776 test_smb2_bench_path_contention_progress
,
778 torture_assert_goto(state
->tctx
, te
!= NULL
,
779 state
->ok
, asserted
, "tevent_add_timer");
781 if (!torture_setting_bool(state
->tctx
, "progress", true)) {
785 avs_open_latency
= total_open_latency
/ num_opens
;
786 avs_close_latency
= total_close_latency
/ num_closes
;
788 torture_comment(state
->tctx
,
790 "open[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f] "
791 "close[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f] \r",
792 timeval_elapsed(&state
->starttime
),
793 (unsigned long long)num_opens
,
797 (unsigned long long)num_closes
,
804 avs_open_latency
= state
->opens
.total_latency
/ state
->opens
.num_finished
;
805 avs_close_latency
= state
->closes
.total_latency
/ state
->closes
.num_finished
;
806 num_opens
= state
->opens
.num_finished
/ state
->timelimit
;
807 num_closes
= state
->closes
.num_finished
/ state
->timelimit
;
809 torture_comment(state
->tctx
,
811 "open[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f] "
812 "close[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f]\n",
813 timeval_elapsed(&state
->starttime
),
814 (unsigned long long)num_opens
,
816 state
->opens
.min_latency
,
817 state
->opens
.max_latency
,
818 (unsigned long long)num_closes
,
820 state
->closes
.min_latency
,
821 state
->closes
.max_latency
);
827 bool test_smb2_bench_path_contention_shared(struct torture_context
*tctx
,
828 struct smb2_tree
*tree
)
830 struct test_smb2_bench_path_contention_shared_state
*state
= NULL
;
832 int torture_nprocs
= torture_setting_int(tctx
, "nprocs", 4);
833 int torture_qdepth
= torture_setting_int(tctx
, "qdepth", 1);
836 int timelimit
= torture_setting_int(tctx
, "timelimit", 10);
837 const char *path
= torture_setting_string(tctx
, "bench_path", "");
838 struct smb2_create open_io
= { .level
= RAW_OPEN_SMB2
, };
839 struct smb2_close close_io
= { .level
= RAW_CLOSE_SMB2
, };
840 struct tevent_timer
*te
= NULL
;
841 uint32_t timeout_msec
;
843 state
= talloc_zero(tctx
, struct test_smb2_bench_path_contention_shared_state
);
844 torture_assert(tctx
, state
!= NULL
, __location__
);
846 state
->num_conns
= torture_nprocs
;
847 state
->conns
= talloc_zero_array(state
,
848 struct test_smb2_bench_path_contention_shared_conn
,
850 torture_assert(tctx
, state
->conns
!= NULL
, __location__
);
851 state
->num_loops
= torture_nprocs
* torture_qdepth
;
852 state
->loops
= talloc_zero_array(state
,
853 struct test_smb2_bench_path_contention_shared_loop
,
855 torture_assert(tctx
, state
->loops
!= NULL
, __location__
);
857 state
->timelimit
= MAX(timelimit
, 1);
859 open_io
.in
.desired_access
= SEC_DIR_READ_ATTRIBUTE
;
860 open_io
.in
.alloc_size
= 0;
861 open_io
.in
.file_attributes
= 0;
862 open_io
.in
.share_access
= FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
;
863 open_io
.in
.create_disposition
= FILE_OPEN
;
864 open_io
.in
.create_options
= FILE_OPEN_REPARSE_POINT
;
865 open_io
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
866 open_io
.in
.security_flags
= 0;
867 open_io
.in
.fname
= path
;
868 open_io
.in
.create_flags
= NTCREATEX_FLAGS_EXTENDED
;
869 open_io
.in
.oplock_level
= SMB2_OPLOCK_LEVEL_NONE
;
871 timeout_msec
= tree
->session
->transport
->options
.request_timeout
* 1000;
873 torture_comment(tctx
, "Opening %zd connections\n", state
->num_conns
);
875 for (i
=0;i
<state
->num_conns
;i
++) {
876 struct smb2_tree
*ct
= NULL
;
877 DATA_BLOB out_input_buffer
= data_blob_null
;
878 DATA_BLOB out_output_buffer
= data_blob_null
;
881 state
->conns
[i
].state
= state
;
882 state
->conns
[i
].idx
= i
;
884 if (!torture_smb2_connection(tctx
, &ct
)) {
885 torture_comment(tctx
, "Failed opening %zd/%zd connections\n", i
, state
->num_conns
);
888 state
->conns
[i
].tree
= talloc_steal(state
->conns
, ct
);
890 smb2cli_conn_set_max_credits(ct
->session
->transport
->conn
, 8192);
891 smb2cli_ioctl(ct
->session
->transport
->conn
,
893 ct
->session
->smbXcli
,
895 UINT64_MAX
, /* in_fid_persistent */
896 UINT64_MAX
, /* in_fid_volatile */
898 0, /* in_max_input_length */
899 NULL
, /* in_input_buffer */
900 1, /* in_max_output_length */
901 NULL
, /* in_output_buffer */
902 SMB2_IOCTL_FLAG_IS_FSCTL
,
907 smbXcli_conn_is_connected(ct
->session
->transport
->conn
),
908 "smbXcli_conn_is_connected");
909 for (pcli
= 0; pcli
< torture_qdepth
; pcli
++) {
910 struct test_smb2_bench_path_contention_shared_loop
*loop
= &state
->loops
[li
];
914 loop
->conn
= &state
->conns
[i
];
915 loop
->im
= tevent_create_immediate(state
->loops
);
916 torture_assert(tctx
, loop
->im
!= NULL
, __location__
);
917 loop
->opens
.io
= open_io
;
918 loop
->closes
.io
= close_io
;
920 tevent_schedule_immediate(loop
->im
,
922 test_smb2_bench_path_contention_loop_start
,
927 torture_comment(tctx
, "Opened %zu connections with qdepth=%d => %zu loops\n",
928 state
->num_conns
, torture_qdepth
, state
->num_loops
);
930 torture_comment(tctx
, "Running for %d seconds\n", state
->timelimit
);
932 state
->starttime
= timeval_current();
934 te
= tevent_add_timer(tctx
->ev
,
936 timeval_current_ofs(1, 0),
937 test_smb2_bench_path_contention_progress
,
939 torture_assert(tctx
, te
!= NULL
, __location__
);
941 while (!state
->stop
) {
942 int rc
= tevent_loop_once(tctx
->ev
);
943 torture_assert_int_equal(tctx
, rc
, 0, "tevent_loop_once");
946 torture_comment(tctx
, "%.2f seconds\n", timeval_elapsed(&state
->starttime
));
952 stress testing read iops
955 struct test_smb2_bench_read_conn
;
956 struct test_smb2_bench_read_loop
;
958 struct test_smb2_bench_read_state
{
959 struct torture_context
*tctx
;
961 struct test_smb2_bench_read_conn
*conns
;
963 struct test_smb2_bench_read_loop
*loops
;
964 size_t pending_loops
;
966 struct timeval starttime
;
969 uint64_t num_finished
;
970 double total_latency
;
977 struct test_smb2_bench_read_conn
{
978 struct test_smb2_bench_read_state
*state
;
980 struct smb2_tree
*tree
;
983 struct test_smb2_bench_read_loop
{
984 struct test_smb2_bench_read_state
*state
;
985 struct test_smb2_bench_read_conn
*conn
;
987 struct tevent_immediate
*im
;
989 struct smb2_handle handle
;
990 struct tevent_req
*req
;
991 struct timeval starttime
;
992 uint64_t num_started
;
993 uint64_t num_finished
;
994 uint64_t total_finished
;
995 uint64_t max_finished
;
996 double total_latency
;
1002 static void test_smb2_bench_read_loop_do(
1003 struct test_smb2_bench_read_loop
*loop
);
1005 static void test_smb2_bench_read_loop_start(struct tevent_context
*ctx
,
1006 struct tevent_immediate
*im
,
1009 struct test_smb2_bench_read_loop
*loop
=
1010 (struct test_smb2_bench_read_loop
*)
1013 test_smb2_bench_read_loop_do(loop
);
1016 static void test_smb2_bench_read_loop_done(struct tevent_req
*req
);
1018 static void test_smb2_bench_read_loop_do(
1019 struct test_smb2_bench_read_loop
*loop
)
1021 struct test_smb2_bench_read_state
*state
= loop
->state
;
1022 uint32_t timeout_msec
;
1024 timeout_msec
= loop
->conn
->tree
->session
->transport
->options
.request_timeout
* 1000;
1026 loop
->num_started
+= 1;
1027 loop
->starttime
= timeval_current();
1028 loop
->req
= smb2cli_read_send(state
->loops
,
1030 loop
->conn
->tree
->session
->transport
->conn
,
1032 loop
->conn
->tree
->session
->smbXcli
,
1033 loop
->conn
->tree
->smbXcli
,
1034 state
->io_size
, /* length */
1036 loop
->handle
.data
[0],/* fid_persistent */
1037 loop
->handle
.data
[1],/* fid_volatile */
1038 state
->io_size
, /* minimum_count */
1039 0); /* remaining_bytes */
1040 torture_assert_goto(state
->tctx
, loop
->req
!= NULL
,
1041 state
->ok
, asserted
, "smb2cli_read_send");
1043 tevent_req_set_callback(loop
->req
,
1044 test_smb2_bench_read_loop_done
,
1051 static void test_smb2_bench_read_loop_done(struct tevent_req
*req
)
1053 struct test_smb2_bench_read_loop
*loop
=
1054 (struct test_smb2_bench_read_loop
*)
1055 _tevent_req_callback_data(req
);
1056 struct test_smb2_bench_read_state
*state
= loop
->state
;
1057 double latency
= timeval_elapsed(&loop
->starttime
);
1058 TALLOC_CTX
*frame
= talloc_stackframe();
1059 uint8_t *data
= NULL
;
1060 uint32_t data_length
= 0;
1062 torture_assert_goto(state
->tctx
, loop
->req
== req
,
1063 state
->ok
, asserted
, __location__
);
1064 loop
->error
= smb2cli_read_recv(req
, frame
, &data
, &data_length
);
1065 torture_assert_ntstatus_ok_goto(state
->tctx
, loop
->error
,
1066 state
->ok
, asserted
, __location__
);
1067 torture_assert_u32_equal_goto(state
->tctx
, data_length
, state
->io_size
,
1068 state
->ok
, asserted
, __location__
);
1069 SMB_ASSERT(latency
>= 0.000001);
1071 if (loop
->num_finished
== 0) {
1073 loop
->min_latency
= latency
;
1074 loop
->max_latency
= latency
;
1077 loop
->num_finished
+= 1;
1078 loop
->total_finished
+= 1;
1079 loop
->total_latency
+= latency
;
1081 if (latency
< loop
->min_latency
) {
1082 loop
->min_latency
= latency
;
1085 if (latency
> loop
->max_latency
) {
1086 loop
->max_latency
= latency
;
1089 if (loop
->total_finished
>= loop
->max_finished
) {
1090 if (state
->pending_loops
> 0) {
1091 state
->pending_loops
-= 1;
1093 if (state
->pending_loops
== 0) {
1099 test_smb2_bench_read_loop_do(loop
);
1106 static void test_smb2_bench_read_progress(struct tevent_context
*ev
,
1107 struct tevent_timer
*te
,
1108 struct timeval current_time
,
1111 struct test_smb2_bench_read_state
*state
=
1112 (struct test_smb2_bench_read_state
*)private_data
;
1113 uint64_t num_reads
= 0;
1114 double total_read_latency
= 0;
1115 double min_read_latency
= 0;
1116 double max_read_latency
= 0;
1117 double avs_read_latency
= 0;
1120 state
->timecount
+= 1;
1122 for (i
=0;i
<state
->num_loops
;i
++) {
1123 struct test_smb2_bench_read_loop
*loop
=
1126 num_reads
+= loop
->num_finished
;
1127 total_read_latency
+= loop
->total_latency
;
1128 if (min_read_latency
== 0.0 && loop
->min_latency
!= 0.0) {
1129 min_read_latency
= loop
->min_latency
;
1131 if (loop
->min_latency
< min_read_latency
) {
1132 min_read_latency
= loop
->min_latency
;
1134 if (max_read_latency
== 0.0) {
1135 max_read_latency
= loop
->max_latency
;
1137 if (loop
->max_latency
> max_read_latency
) {
1138 max_read_latency
= loop
->max_latency
;
1140 loop
->num_finished
= 0;
1141 loop
->total_latency
= 0.0;
1144 state
->num_finished
+= num_reads
;
1145 state
->total_latency
+= total_read_latency
;
1146 if (state
->min_latency
== 0.0 && min_read_latency
!= 0.0) {
1147 state
->min_latency
= min_read_latency
;
1149 if (min_read_latency
< state
->min_latency
) {
1150 state
->min_latency
= min_read_latency
;
1152 if (state
->max_latency
== 0.0) {
1153 state
->max_latency
= max_read_latency
;
1155 if (max_read_latency
> state
->max_latency
) {
1156 state
->max_latency
= max_read_latency
;
1159 if (state
->timecount
< state
->timelimit
) {
1160 te
= tevent_add_timer(state
->tctx
->ev
,
1162 timeval_current_ofs(1, 0),
1163 test_smb2_bench_read_progress
,
1165 torture_assert_goto(state
->tctx
, te
!= NULL
,
1166 state
->ok
, asserted
, "tevent_add_timer");
1168 if (!torture_setting_bool(state
->tctx
, "progress", true)) {
1172 avs_read_latency
= total_read_latency
/ num_reads
;
1174 torture_comment(state
->tctx
,
1176 "read[num/s=%llu,bytes/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f] \r",
1177 timeval_elapsed(&state
->starttime
),
1178 (unsigned long long)num_reads
,
1179 (unsigned long long)num_reads
*state
->io_size
,
1186 avs_read_latency
= state
->total_latency
/ state
->num_finished
;
1187 num_reads
= state
->num_finished
/ state
->timelimit
;
1189 torture_comment(state
->tctx
,
1191 "read[num/s=%llu,bytes/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f]\n",
1192 timeval_elapsed(&state
->starttime
),
1193 (unsigned long long)num_reads
,
1194 (unsigned long long)num_reads
*state
->io_size
,
1197 state
->max_latency
);
1203 static bool test_smb2_bench_read(struct torture_context
*tctx
,
1204 struct smb2_tree
*tree
)
1206 struct test_smb2_bench_read_state
*state
= NULL
;
1208 int torture_nprocs
= torture_setting_int(tctx
, "nprocs", 4);
1209 int torture_qdepth
= torture_setting_int(tctx
, "qdepth", 1);
1210 int torture_io_size
= torture_setting_int(tctx
, "io_size", 4096);
1213 int looplimit
= torture_setting_int(tctx
, "looplimit", -1);
1214 int timelimit
= torture_setting_int(tctx
, "timelimit", 10);
1215 struct tevent_timer
*te
= NULL
;
1216 uint32_t timeout_msec
;
1217 const char *dname
= "bench_read_dir";
1218 const char *unique
= generate_random_str(tctx
, 8);
1219 struct smb2_handle dh
;
1222 smb2_deltree(tree
, dname
);
1224 status
= torture_smb2_testdir(tree
, dname
, &dh
);
1225 CHECK_STATUS(status
, NT_STATUS_OK
);
1226 status
= smb2_util_close(tree
, dh
);
1227 CHECK_STATUS(status
, NT_STATUS_OK
);
1229 state
= talloc_zero(tctx
, struct test_smb2_bench_read_state
);
1230 torture_assert(tctx
, state
!= NULL
, __location__
);
1232 state
->num_conns
= torture_nprocs
;
1233 state
->conns
= talloc_zero_array(state
,
1234 struct test_smb2_bench_read_conn
,
1236 torture_assert(tctx
, state
->conns
!= NULL
, __location__
);
1237 state
->num_loops
= torture_nprocs
* torture_qdepth
;
1238 state
->loops
= talloc_zero_array(state
,
1239 struct test_smb2_bench_read_loop
,
1241 torture_assert(tctx
, state
->loops
!= NULL
, __location__
);
1243 state
->timelimit
= MAX(timelimit
, 1);
1244 state
->io_size
= MAX(torture_io_size
, 1);
1245 state
->io_size
= MIN(state
->io_size
, 16*1024*1024);
1247 timeout_msec
= tree
->session
->transport
->options
.request_timeout
* 1000;
1249 torture_comment(tctx
, "Opening %zu connections\n", state
->num_conns
);
1251 for (i
=0;i
<state
->num_conns
;i
++) {
1252 struct smb2_tree
*ct
= NULL
;
1253 DATA_BLOB out_input_buffer
= data_blob_null
;
1254 DATA_BLOB out_output_buffer
= data_blob_null
;
1257 state
->conns
[i
].state
= state
;
1258 state
->conns
[i
].idx
= i
;
1260 if (!torture_smb2_connection(tctx
, &ct
)) {
1261 torture_comment(tctx
, "Failed opening %zu/%zu connections\n", i
, state
->num_conns
);
1264 state
->conns
[i
].tree
= talloc_steal(state
->conns
, ct
);
1266 smb2cli_conn_set_max_credits(ct
->session
->transport
->conn
, 8192);
1267 smb2cli_ioctl(ct
->session
->transport
->conn
,
1269 ct
->session
->smbXcli
,
1271 UINT64_MAX
, /* in_fid_persistent */
1272 UINT64_MAX
, /* in_fid_volatile */
1274 0, /* in_max_input_length */
1275 NULL
, /* in_input_buffer */
1276 1, /* in_max_output_length */
1277 NULL
, /* in_output_buffer */
1278 SMB2_IOCTL_FLAG_IS_FSCTL
,
1281 &out_output_buffer
);
1282 torture_assert(tctx
,
1283 smbXcli_conn_is_connected(ct
->session
->transport
->conn
),
1284 "smbXcli_conn_is_connected");
1286 for (pcli
= 0; pcli
< torture_qdepth
; pcli
++) {
1287 struct test_smb2_bench_read_loop
*loop
= &state
->loops
[li
];
1288 struct smb2_create cr
;
1289 union smb_setfileinfo sfinfo
;
1292 if (looplimit
!= -1) {
1293 loop
->max_finished
= looplimit
;
1295 loop
->max_finished
= UINT64_MAX
;
1297 loop
->state
= state
;
1298 loop
->conn
= &state
->conns
[i
];
1299 loop
->im
= tevent_create_immediate(state
->loops
);
1300 torture_assert(tctx
, loop
->im
!= NULL
, __location__
);
1302 loop
->fname
= talloc_asprintf(state
->loops
,
1303 "%s\\%s_loop_%zu_conn_%zu_loop_%zu.dat",
1304 dname
, unique
, li
, i
, pcli
);
1305 torture_assert(tctx
, loop
->fname
!= NULL
, __location__
);
1307 /* reasonable default parameters */
1309 cr
.in
.create_flags
= NTCREATEX_FLAGS_EXTENDED
;
1310 cr
.in
.alloc_size
= state
->io_size
;
1311 cr
.in
.desired_access
= SEC_RIGHTS_FILE_ALL
;
1312 cr
.in
.file_attributes
= FILE_ATTRIBUTE_NORMAL
;
1313 cr
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
1314 cr
.in
.create_disposition
= NTCREATEX_DISP_CREATE
;
1315 cr
.in
.create_options
=
1316 NTCREATEX_OPTIONS_DELETE_ON_CLOSE
|
1317 NTCREATEX_OPTIONS_NON_DIRECTORY_FILE
;
1318 cr
.in
.impersonation_level
= SMB2_IMPERSONATION_ANONYMOUS
;
1319 cr
.in
.security_flags
= 0;
1320 cr
.in
.fname
= loop
->fname
;
1321 status
= smb2_create(state
->conns
[i
].tree
, tctx
, &cr
);
1322 CHECK_STATUS(status
, NT_STATUS_OK
);
1323 loop
->handle
= cr
.out
.file
.handle
;
1325 ZERO_STRUCT(sfinfo
);
1326 sfinfo
.end_of_file_info
.level
= RAW_SFILEINFO_END_OF_FILE_INFORMATION
;
1327 sfinfo
.end_of_file_info
.in
.file
.handle
= loop
->handle
;
1328 sfinfo
.end_of_file_info
.in
.size
= state
->io_size
;
1329 status
= smb2_setinfo_file(state
->conns
[i
].tree
, &sfinfo
);
1330 CHECK_STATUS(status
, NT_STATUS_OK
);
1332 tevent_schedule_immediate(loop
->im
,
1334 test_smb2_bench_read_loop_start
,
1339 torture_comment(tctx
, "Opened %zu connections with qdepth=%d => %zu loops\n",
1340 state
->num_conns
, torture_qdepth
, state
->num_loops
);
1342 torture_comment(tctx
, "Running for %d seconds\n", state
->timelimit
);
1344 state
->starttime
= timeval_current();
1345 state
->pending_loops
= state
->num_loops
;
1347 te
= tevent_add_timer(tctx
->ev
,
1349 timeval_current_ofs(1, 0),
1350 test_smb2_bench_read_progress
,
1352 torture_assert(tctx
, te
!= NULL
, __location__
);
1354 while (!state
->stop
) {
1355 int rc
= tevent_loop_once(tctx
->ev
);
1356 torture_assert_int_equal(tctx
, rc
, 0, "tevent_loop_once");
1359 torture_comment(tctx
, "%.2f seconds\n", timeval_elapsed(&state
->starttime
));
1361 smb2_deltree(tree
, dname
);
1366 stress testing session setups
1369 struct test_smb2_bench_session_setup_shared_conn
;
1370 struct test_smb2_bench_session_setup_shared_loop
;
1372 struct test_smb2_bench_session_setup_shared_state
{
1373 struct torture_context
*tctx
;
1374 struct cli_credentials
*credentials
;
1375 struct gensec_settings
*gensec_settings
;
1377 struct test_smb2_bench_session_setup_shared_conn
*conns
;
1379 struct test_smb2_bench_session_setup_shared_loop
*loops
;
1380 struct timeval starttime
;
1384 uint64_t num_finished
;
1385 double total_latency
;
1390 uint64_t num_finished
;
1391 double total_latency
;
1399 struct test_smb2_bench_session_setup_shared_conn
{
1400 struct test_smb2_bench_session_setup_shared_state
*state
;
1402 struct smb2_transport
*transport
;
1405 struct test_smb2_bench_session_setup_shared_loop
{
1406 struct test_smb2_bench_session_setup_shared_state
*state
;
1407 struct test_smb2_bench_session_setup_shared_conn
*conn
;
1409 struct smb2_session
*session
;
1410 struct tevent_immediate
*im
;
1412 struct tevent_req
*req
;
1413 struct timeval starttime
;
1414 uint64_t num_started
;
1415 uint64_t num_finished
;
1416 double total_latency
;
1421 struct smb2_request
*req
;
1422 struct timeval starttime
;
1423 uint64_t num_started
;
1424 uint64_t num_finished
;
1425 double total_latency
;
1432 static void test_smb2_bench_session_setup_loop_do_setup(
1433 struct test_smb2_bench_session_setup_shared_loop
*loop
);
1435 static void test_smb2_bench_session_setup_loop_start(struct tevent_context
*ctx
,
1436 struct tevent_immediate
*im
,
1439 struct test_smb2_bench_session_setup_shared_loop
*loop
=
1440 (struct test_smb2_bench_session_setup_shared_loop
*)
1443 test_smb2_bench_session_setup_loop_do_setup(loop
);
1446 static void test_smb2_bench_session_setup_loop_done_setup(struct tevent_req
*subreq
);
1448 static void test_smb2_bench_session_setup_loop_do_setup(
1449 struct test_smb2_bench_session_setup_shared_loop
*loop
)
1451 struct test_smb2_bench_session_setup_shared_state
*state
= loop
->state
;
1453 loop
->session
= smb2_session_init(loop
->conn
->transport
,
1454 state
->gensec_settings
,
1455 loop
->conn
->transport
);
1456 torture_assert_goto(state
->tctx
, loop
->session
!= NULL
,
1457 state
->ok
, asserted
, "smb2_session_init");
1458 talloc_steal(state
->conns
, loop
->conn
->transport
);
1460 loop
->setups
.num_started
+= 1;
1461 loop
->setups
.starttime
= timeval_current();
1462 loop
->setups
.req
= smb2_session_setup_spnego_send(loop
->session
,
1466 0); /* previous_session_id */
1467 torture_assert_goto(state
->tctx
, loop
->setups
.req
!= NULL
,
1468 state
->ok
, asserted
,
1469 "smb2_session_setup_spnego_send");
1471 tevent_req_set_callback(loop
->setups
.req
,
1472 test_smb2_bench_session_setup_loop_done_setup
,
1479 static void test_smb2_bench_session_setup_loop_do_logoff(
1480 struct test_smb2_bench_session_setup_shared_loop
*loop
);
1482 static void test_smb2_bench_session_setup_loop_done_setup(struct tevent_req
*subreq
)
1484 struct test_smb2_bench_session_setup_shared_loop
*loop
=
1485 (struct test_smb2_bench_session_setup_shared_loop
*)
1486 tevent_req_callback_data_void(subreq
);
1487 struct test_smb2_bench_session_setup_shared_state
*state
= loop
->state
;
1488 double latency
= timeval_elapsed(&loop
->setups
.starttime
);
1489 TALLOC_CTX
*frame
= talloc_stackframe();
1491 torture_assert_goto(state
->tctx
, loop
->setups
.req
== subreq
,
1492 state
->ok
, asserted
, __location__
);
1493 loop
->setups
.req
= NULL
;
1494 loop
->error
= smb2_session_setup_spnego_recv(subreq
);
1495 TALLOC_FREE(subreq
);
1496 torture_assert_ntstatus_ok_goto(state
->tctx
, loop
->error
,
1497 state
->ok
, asserted
, __location__
);
1498 SMB_ASSERT(latency
>= 0.000001);
1500 if (loop
->setups
.num_finished
== 0) {
1502 loop
->setups
.min_latency
= latency
;
1503 loop
->setups
.max_latency
= latency
;
1506 loop
->setups
.num_finished
+= 1;
1507 loop
->setups
.total_latency
+= latency
;
1509 if (latency
< loop
->setups
.min_latency
) {
1510 loop
->setups
.min_latency
= latency
;
1513 if (latency
> loop
->setups
.max_latency
) {
1514 loop
->setups
.max_latency
= latency
;
1518 test_smb2_bench_session_setup_loop_do_logoff(loop
);
1525 static void test_smb2_bench_session_setup_loop_done_logoff(struct smb2_request
*req
);
1527 static void test_smb2_bench_session_setup_loop_do_logoff(
1528 struct test_smb2_bench_session_setup_shared_loop
*loop
)
1530 struct test_smb2_bench_session_setup_shared_state
*state
= loop
->state
;
1532 loop
->logoffs
.num_started
+= 1;
1533 loop
->logoffs
.starttime
= timeval_current();
1534 loop
->logoffs
.req
= smb2_logoff_send(loop
->session
);
1535 torture_assert_goto(state
->tctx
, loop
->logoffs
.req
!= NULL
,
1536 state
->ok
, asserted
, "smb2_logoff_send");
1538 loop
->logoffs
.req
->async
.fn
= test_smb2_bench_session_setup_loop_done_logoff
;
1539 loop
->logoffs
.req
->async
.private_data
= loop
;
1545 static void test_smb2_bench_session_setup_loop_done_logoff(struct smb2_request
*req
)
1547 struct test_smb2_bench_session_setup_shared_loop
*loop
=
1548 (struct test_smb2_bench_session_setup_shared_loop
*)
1549 req
->async
.private_data
;
1550 struct test_smb2_bench_session_setup_shared_state
*state
= loop
->state
;
1551 double latency
= timeval_elapsed(&loop
->logoffs
.starttime
);
1553 torture_assert_goto(state
->tctx
, loop
->logoffs
.req
== req
,
1554 state
->ok
, asserted
, __location__
);
1555 loop
->error
= smb2_logoff_recv(req
);
1556 torture_assert_ntstatus_ok_goto(state
->tctx
, loop
->error
,
1557 state
->ok
, asserted
, __location__
);
1558 TALLOC_FREE(loop
->session
);
1559 SMB_ASSERT(latency
>= 0.000001);
1560 if (loop
->logoffs
.num_finished
== 0) {
1562 loop
->logoffs
.min_latency
= latency
;
1563 loop
->logoffs
.max_latency
= latency
;
1565 loop
->logoffs
.num_finished
+= 1;
1567 loop
->logoffs
.total_latency
+= latency
;
1569 if (latency
< loop
->logoffs
.min_latency
) {
1570 loop
->logoffs
.min_latency
= latency
;
1573 if (latency
> loop
->logoffs
.max_latency
) {
1574 loop
->logoffs
.max_latency
= latency
;
1577 test_smb2_bench_session_setup_loop_do_setup(loop
);
1583 static void test_smb2_bench_session_setup_progress(struct tevent_context
*ev
,
1584 struct tevent_timer
*te
,
1585 struct timeval current_time
,
1588 struct test_smb2_bench_session_setup_shared_state
*state
=
1589 (struct test_smb2_bench_session_setup_shared_state
*)private_data
;
1590 uint64_t num_setups
= 0;
1591 double total_setup_latency
= 0;
1592 double min_setup_latency
= 0;
1593 double max_setup_latency
= 0;
1594 double avs_setup_latency
= 0;
1595 uint64_t num_logoffs
= 0;
1596 double total_logoff_latency
= 0;
1597 double min_logoff_latency
= 0;
1598 double max_logoff_latency
= 0;
1599 double avs_logoff_latency
= 0;
1602 state
->timecount
+= 1;
1604 for (i
=0;i
<state
->num_loops
;i
++) {
1605 struct test_smb2_bench_session_setup_shared_loop
*loop
=
1608 num_setups
+= loop
->setups
.num_finished
;
1609 total_setup_latency
+= loop
->setups
.total_latency
;
1610 if (min_setup_latency
== 0.0 && loop
->setups
.min_latency
!= 0.0) {
1611 min_setup_latency
= loop
->setups
.min_latency
;
1613 if (loop
->setups
.min_latency
< min_setup_latency
) {
1614 min_setup_latency
= loop
->setups
.min_latency
;
1616 if (max_setup_latency
== 0.0) {
1617 max_setup_latency
= loop
->setups
.max_latency
;
1619 if (loop
->setups
.max_latency
> max_setup_latency
) {
1620 max_setup_latency
= loop
->setups
.max_latency
;
1622 loop
->setups
.num_finished
= 0;
1623 loop
->setups
.total_latency
= 0.0;
1625 num_logoffs
+= loop
->logoffs
.num_finished
;
1626 total_logoff_latency
+= loop
->logoffs
.total_latency
;
1627 if (min_logoff_latency
== 0.0 && loop
->logoffs
.min_latency
!= 0.0) {
1628 min_logoff_latency
= loop
->logoffs
.min_latency
;
1630 if (loop
->logoffs
.min_latency
< min_logoff_latency
) {
1631 min_logoff_latency
= loop
->logoffs
.min_latency
;
1633 if (max_logoff_latency
== 0.0) {
1634 max_logoff_latency
= loop
->logoffs
.max_latency
;
1636 if (loop
->logoffs
.max_latency
> max_logoff_latency
) {
1637 max_logoff_latency
= loop
->logoffs
.max_latency
;
1639 loop
->logoffs
.num_finished
= 0;
1640 loop
->logoffs
.total_latency
= 0.0;
1643 state
->setups
.num_finished
+= num_setups
;
1644 state
->setups
.total_latency
+= total_setup_latency
;
1645 if (state
->setups
.min_latency
== 0.0 && min_setup_latency
!= 0.0) {
1646 state
->setups
.min_latency
= min_setup_latency
;
1648 if (min_setup_latency
< state
->setups
.min_latency
) {
1649 state
->setups
.min_latency
= min_setup_latency
;
1651 if (state
->setups
.max_latency
== 0.0) {
1652 state
->setups
.max_latency
= max_setup_latency
;
1654 if (max_setup_latency
> state
->setups
.max_latency
) {
1655 state
->setups
.max_latency
= max_setup_latency
;
1658 state
->logoffs
.num_finished
+= num_logoffs
;
1659 state
->logoffs
.total_latency
+= total_logoff_latency
;
1660 if (state
->logoffs
.min_latency
== 0.0 && min_logoff_latency
!= 0.0) {
1661 state
->logoffs
.min_latency
= min_logoff_latency
;
1663 if (min_logoff_latency
< state
->logoffs
.min_latency
) {
1664 state
->logoffs
.min_latency
= min_logoff_latency
;
1666 if (state
->logoffs
.max_latency
== 0.0) {
1667 state
->logoffs
.max_latency
= max_logoff_latency
;
1669 if (max_logoff_latency
> state
->logoffs
.max_latency
) {
1670 state
->logoffs
.max_latency
= max_logoff_latency
;
1673 if (state
->timecount
< state
->timelimit
) {
1674 te
= tevent_add_timer(state
->tctx
->ev
,
1676 timeval_current_ofs(1, 0),
1677 test_smb2_bench_session_setup_progress
,
1679 torture_assert_goto(state
->tctx
, te
!= NULL
,
1680 state
->ok
, asserted
, "tevent_add_timer");
1682 if (!torture_setting_bool(state
->tctx
, "progress", true)) {
1686 avs_setup_latency
= total_setup_latency
/ num_setups
;
1687 avs_logoff_latency
= total_logoff_latency
/ num_logoffs
;
1689 torture_comment(state
->tctx
,
1691 "setup[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f] "
1692 "logoff[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f] \r",
1693 timeval_elapsed(&state
->starttime
),
1694 (unsigned long long)num_setups
,
1698 (unsigned long long)num_logoffs
,
1701 max_logoff_latency
);
1705 avs_setup_latency
= state
->setups
.total_latency
/ state
->setups
.num_finished
;
1706 avs_logoff_latency
= state
->logoffs
.total_latency
/ state
->logoffs
.num_finished
;
1707 num_setups
= state
->setups
.num_finished
/ state
->timelimit
;
1708 num_logoffs
= state
->logoffs
.num_finished
/ state
->timelimit
;
1710 torture_comment(state
->tctx
,
1712 "setup[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f] "
1713 "logoff[num/s=%llu,avslat=%.6f,minlat=%.6f,maxlat=%.6f]\n",
1714 timeval_elapsed(&state
->starttime
),
1715 (unsigned long long)num_setups
,
1717 state
->setups
.min_latency
,
1718 state
->setups
.max_latency
,
1719 (unsigned long long)num_logoffs
,
1721 state
->logoffs
.min_latency
,
1722 state
->logoffs
.max_latency
);
1728 static bool test_smb2_bench_session_setup(struct torture_context
*tctx
,
1729 struct smb2_tree
*tree
)
1731 struct test_smb2_bench_session_setup_shared_state
*state
= NULL
;
1733 int torture_nprocs
= torture_setting_int(tctx
, "nprocs", 4);
1734 int torture_qdepth
= torture_setting_int(tctx
, "qdepth", 1);
1737 int timelimit
= torture_setting_int(tctx
, "timelimit", 10);
1738 struct tevent_timer
*te
= NULL
;
1739 uint32_t timeout_msec
;
1741 state
= talloc_zero(tctx
, struct test_smb2_bench_session_setup_shared_state
);
1742 torture_assert(tctx
, state
!= NULL
, __location__
);
1744 state
->credentials
= samba_cmdline_get_creds();
1745 torture_assert(tctx
, state
->credentials
!= NULL
, __location__
);
1746 state
->gensec_settings
= lpcfg_gensec_settings(state
, tctx
->lp_ctx
);
1747 torture_assert(tctx
, state
->gensec_settings
!= NULL
, __location__
);
1748 state
->num_conns
= torture_nprocs
;
1749 state
->conns
= talloc_zero_array(state
,
1750 struct test_smb2_bench_session_setup_shared_conn
,
1752 torture_assert(tctx
, state
->conns
!= NULL
, __location__
);
1753 state
->num_loops
= torture_nprocs
* torture_qdepth
;
1754 state
->loops
= talloc_zero_array(state
,
1755 struct test_smb2_bench_session_setup_shared_loop
,
1757 torture_assert(tctx
, state
->loops
!= NULL
, __location__
);
1759 state
->timelimit
= MAX(timelimit
, 1);
1761 timeout_msec
= tree
->session
->transport
->options
.request_timeout
* 1000;
1763 torture_comment(tctx
, "Opening %zd connections\n", state
->num_conns
);
1765 for (i
=0;i
<state
->num_conns
;i
++) {
1766 struct smb2_tree
*ct
= NULL
;
1767 DATA_BLOB out_input_buffer
= data_blob_null
;
1768 DATA_BLOB out_output_buffer
= data_blob_null
;
1771 state
->conns
[i
].state
= state
;
1772 state
->conns
[i
].idx
= i
;
1774 if (!torture_smb2_connection(tctx
, &ct
)) {
1775 torture_comment(tctx
, "Failed opening %zd/%zd connections\n", i
, state
->num_conns
);
1778 talloc_steal(state
->conns
, ct
);
1779 state
->conns
[i
].transport
= ct
->session
->transport
;
1781 smb2cli_conn_set_max_credits(ct
->session
->transport
->conn
, 8192);
1782 smb2cli_ioctl(ct
->session
->transport
->conn
,
1784 ct
->session
->smbXcli
,
1786 UINT64_MAX
, /* in_fid_persistent */
1787 UINT64_MAX
, /* in_fid_volatile */
1789 0, /* in_max_input_length */
1790 NULL
, /* in_input_buffer */
1791 1, /* in_max_output_length */
1792 NULL
, /* in_output_buffer */
1793 SMB2_IOCTL_FLAG_IS_FSCTL
,
1796 &out_output_buffer
);
1797 torture_assert(tctx
,
1798 smbXcli_conn_is_connected(ct
->session
->transport
->conn
),
1799 "smbXcli_conn_is_connected");
1800 for (pcli
= 0; pcli
< torture_qdepth
; pcli
++) {
1801 struct test_smb2_bench_session_setup_shared_loop
*loop
= &state
->loops
[li
];
1804 loop
->state
= state
;
1805 loop
->conn
= &state
->conns
[i
];
1806 loop
->im
= tevent_create_immediate(state
->loops
);
1807 torture_assert(tctx
, loop
->im
!= NULL
, __location__
);
1809 tevent_schedule_immediate(loop
->im
,
1811 test_smb2_bench_session_setup_loop_start
,
1816 torture_comment(tctx
, "Opened %zu connections with qdepth=%d => %zu loops\n",
1817 state
->num_conns
, torture_qdepth
, state
->num_loops
);
1819 torture_comment(tctx
, "Running for %d seconds\n", state
->timelimit
);
1821 state
->starttime
= timeval_current();
1823 te
= tevent_add_timer(tctx
->ev
,
1825 timeval_current_ofs(1, 0),
1826 test_smb2_bench_session_setup_progress
,
1828 torture_assert(tctx
, te
!= NULL
, __location__
);
1830 while (!state
->stop
) {
1831 int rc
= tevent_loop_once(tctx
->ev
);
1832 torture_assert_int_equal(tctx
, rc
, 0, "tevent_loop_once");
1835 torture_comment(tctx
, "%.2f seconds\n", timeval_elapsed(&state
->starttime
));
1840 struct torture_suite
*torture_smb2_bench_init(TALLOC_CTX
*ctx
)
1842 struct torture_suite
*suite
= torture_suite_create(ctx
, "bench");
1844 torture_suite_add_1smb2_test(suite
, "oplock1", test_smb2_bench_oplock
);
1845 torture_suite_add_1smb2_test(suite
, "echo", test_smb2_bench_echo
);
1846 torture_suite_add_1smb2_test(suite
, "path-contention-shared", test_smb2_bench_path_contention_shared
);
1847 torture_suite_add_1smb2_test(suite
, "read", test_smb2_bench_read
);
1848 torture_suite_add_1smb2_test(suite
, "session-setup", test_smb2_bench_session_setup
);
1850 suite
->description
= talloc_strdup(suite
, "SMB2-BENCH tests");