2 Unix SMB/CIFS implementation.
3 SMB torture tester - NBENCH test
4 Copyright (C) Andrew Tridgell 1997-2004
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "libcli/libcli.h"
22 #include "torture/util.h"
23 #include "torture/smbtorture.h"
24 #include "system/filesys.h"
25 #include "system/locale.h"
26 #include "lib/util/smb_strtox.h"
28 #include "torture/nbench/proto.h"
30 int nbench_line_count
= 0;
31 static int timelimit
= 600;
33 static const char *loadfile
;
36 #define ival(s) strtoll(s, NULL, 0)
38 static unsigned long nb_max_retries
;
40 #define NB_RETRY(op) \
41 for (n=0;n<=nb_max_retries && !op;n++) do_reconnect(&cli, tctx, client)
43 static void do_reconnect(struct smbcli_state
**cli
, struct torture_context
*tctx
, int client
)
46 printf("[%d] Reconnecting client %d\n", nbench_line_count
, client
);
47 for (n
=0;n
<nb_max_retries
;n
++) {
48 if (nb_reconnect(cli
, tctx
, client
)) {
49 printf("[%d] Reconnected client %d\n", nbench_line_count
, client
);
53 printf("[%d] Failed to reconnect client %d\n", nbench_line_count
, client
);
57 /* run a test that simulates an approximate netbench client load */
58 static bool run_netbench(struct torture_context
*tctx
, struct smbcli_state
*cli
, int client
)
60 int torture_nprocs
= torture_setting_int(tctx
, "nprocs", 4);
66 double target_rate
= torture_setting_double(tctx
, "targetrate", 0);
70 if (target_rate
!= 0 && client
== 0) {
71 printf("Targeting %.4f MByte/sec\n", target_rate
);
74 nb_setup(cli
, client
);
76 if (torture_nprocs
== 1) {
78 NB_RETRY(torture_setup_dir(cli
, "\\clients"));
82 ret
= asprintf(&cname
, "client%d", client
+1);
87 f
= fopen(loadfile
, "r");
97 while (fgets(line
, sizeof(line
)-1, f
)) {
99 const char **params0
, **params
;
100 unsigned long int tmp
;
105 if ((strlen(line
) > 0) && line
[strlen(line
)-1] == '\n') {
106 line
[strlen(line
)-1] = 0;
109 all_string_sub(line
, "client1", cname
, sizeof(line
));
111 params
= params0
= const_str_list(
112 str_list_make_shell(NULL
, line
, " "));
113 i
= str_list_length(params
);
115 if (i
> 0 && isdigit(params
[0][0])) {
116 double targett
= strtod(params
[0], NULL
);
117 if (target_rate
!= 0) {
118 nbio_target_rate(target_rate
);
120 nbio_time_delay(targett
);
124 } else if (target_rate
!= 0) {
125 nbio_target_rate(target_rate
);
128 if (i
< 2 || params
[0][0] == '#') continue;
130 if (!strncmp(params
[0],"SMB", 3)) {
131 printf("ERROR: You are using a dbench 1 load file\n");
135 if (strncmp(params
[i
-1], "NT_STATUS_", 10) != 0 &&
136 strncmp(params
[i
-1], "0x", 2) != 0) {
137 printf("Badly formed status at line %d\n", nbench_line_count
);
142 /* accept numeric or string status codes */
143 if (strncmp(params
[i
-1], "0x", 2) == 0) {
144 tmp
= smb_strtoul(params
[i
-1],
152 status
= NT_STATUS(tmp
);
154 status
= nt_status_string_to_code(params
[i
-1]);
157 DEBUG(9,("run_netbench(%d): %s %s\n", client
, params
[0], params
[1]));
159 if (!strcmp(params
[0],"NTCreateX")) {
160 NB_RETRY(nb_createx(params
[1], ival(params
[2]), ival(params
[3]),
161 ival(params
[4]), status
));
162 } else if (!strcmp(params
[0],"Close")) {
163 NB_RETRY(nb_close(ival(params
[1]), status
));
164 } else if (!read_only
&& !strcmp(params
[0],"Rename")) {
165 NB_RETRY(nb_rename(params
[1], params
[2], status
, n
>0));
166 } else if (!read_only
&& !strcmp(params
[0],"Unlink")) {
167 NB_RETRY(nb_unlink(params
[1], ival(params
[2]), status
, n
>0));
168 } else if (!read_only
&& !strcmp(params
[0],"Deltree")) {
169 NB_RETRY(nb_deltree(params
[1], n
>0));
170 } else if (!read_only
&& !strcmp(params
[0],"Rmdir")) {
171 NB_RETRY(nb_rmdir(params
[1], status
, n
>0));
172 } else if (!read_only
&& !strcmp(params
[0],"Mkdir")) {
173 NB_RETRY(nb_mkdir(params
[1], status
, n
>0));
174 } else if (!strcmp(params
[0],"QUERY_PATH_INFORMATION")) {
175 NB_RETRY(nb_qpathinfo(params
[1], ival(params
[2]), status
));
176 } else if (!strcmp(params
[0],"QUERY_FILE_INFORMATION")) {
177 NB_RETRY(nb_qfileinfo(ival(params
[1]), ival(params
[2]), status
));
178 } else if (!strcmp(params
[0],"QUERY_FS_INFORMATION")) {
179 NB_RETRY(nb_qfsinfo(ival(params
[1]), status
));
180 } else if (!read_only
&& !strcmp(params
[0],"SET_FILE_INFORMATION")) {
181 NB_RETRY(nb_sfileinfo(ival(params
[1]), ival(params
[2]), status
));
182 } else if (!strcmp(params
[0],"FIND_FIRST")) {
183 NB_RETRY(nb_findfirst(params
[1], ival(params
[2]),
184 ival(params
[3]), ival(params
[4]), status
));
185 } else if (!read_only
&& !strcmp(params
[0],"WriteX")) {
186 NB_RETRY(nb_writex(ival(params
[1]),
187 ival(params
[2]), ival(params
[3]), ival(params
[4]),
189 } else if (!read_only
&& !strcmp(params
[0],"Write")) {
190 NB_RETRY(nb_write(ival(params
[1]),
191 ival(params
[2]), ival(params
[3]), ival(params
[4]),
193 } else if (!strcmp(params
[0],"LockX")) {
194 NB_RETRY(nb_lockx(ival(params
[1]),
195 ival(params
[2]), ival(params
[3]), status
));
196 } else if (!strcmp(params
[0],"UnlockX")) {
197 NB_RETRY(nb_unlockx(ival(params
[1]),
198 ival(params
[2]), ival(params
[3]), status
));
199 } else if (!strcmp(params
[0],"ReadX")) {
200 NB_RETRY(nb_readx(ival(params
[1]),
201 ival(params
[2]), ival(params
[3]), ival(params
[4]),
203 } else if (!strcmp(params
[0],"Flush")) {
204 NB_RETRY(nb_flush(ival(params
[1]), status
));
205 } else if (!strcmp(params
[0],"Sleep")) {
206 nb_sleep(ival(params
[1]), status
);
208 printf("[%d] Unknown operation %s\n", nbench_line_count
, params
[0]);
211 if (n
> nb_max_retries
) {
212 printf("Maximum reconnect retries reached for op '%s'\n", params
[0]);
216 talloc_free(params0
);
218 if (nb_tick()) goto done
;
227 if (!read_only
&& torture_nprocs
== 1) {
228 smbcli_deltree(cli
->tree
, "\\clients");
230 if (!torture_close_connection(cli
)) {
238 /* run a test that simulates an approximate netbench client load */
239 bool torture_nbench(struct torture_context
*torture
)
242 int torture_nprocs
= torture_setting_int(torture
, "nprocs", 4);
243 struct smbcli_state
*cli
;
246 read_only
= torture_setting_bool(torture
, "readonly", false);
248 nb_max_retries
= torture_setting_int(torture
, "nretries", 1);
250 p
= torture_setting_string(torture
, "timelimit", NULL
);
255 warmup
= timelimit
/ 20;
257 loadfile
= torture_setting_string(torture
, "loadfile", NULL
);
258 if (!loadfile
|| !*loadfile
) {
259 loadfile
= "client.txt";
262 if (torture_nprocs
> 1) {
263 if (!torture_open_connection(&cli
, torture
, 0)) {
267 if (!read_only
&& !torture_setup_dir(cli
, "\\clients")) {
272 nbio_shmem(torture_nprocs
, timelimit
, warmup
);
274 printf("Running for %d seconds with load '%s' and warmup %d secs\n",
275 timelimit
, loadfile
, warmup
);
277 /* we need to reset SIGCHLD here as the name resolution
278 library may have changed it. We rely on correct signals
279 from children in the main torture code which reaps
280 children. This is why smbtorture BENCH-NBENCH was sometimes
282 signal(SIGCHLD
, SIG_DFL
);
285 signal(SIGALRM
, nb_alarm
);
287 torture_create_procs(torture
, run_netbench
, &correct
);
290 if (!read_only
&& torture_nprocs
> 1) {
291 smbcli_deltree(cli
->tree
, "\\clients");
294 printf("\nThroughput %g MB/sec\n", nbio_result());
298 NTSTATUS
torture_nbench_init(TALLOC_CTX
*ctx
)
300 struct torture_suite
*suite
= torture_suite_create(
303 torture_suite_add_simple_test(suite
, "nbench", torture_nbench
);
305 suite
->description
= talloc_strdup(suite
, "Benchmarks");
307 torture_register_suite(ctx
, suite
);