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"
27 #include "torture/nbench/proto.h"
29 int nbench_line_count
= 0;
30 static int timelimit
= 600;
32 static const char *loadfile
;
35 #define ival(s) strtoll(s, NULL, 0)
37 static unsigned long nb_max_retries
;
39 #define NB_RETRY(op) \
40 for (n=0;n<=nb_max_retries && !op;n++) do_reconnect(&cli, tctx, client)
42 static void do_reconnect(struct smbcli_state
**cli
, struct torture_context
*tctx
, int client
)
45 printf("[%d] Reconnecting client %d\n", nbench_line_count
, client
);
46 for (n
=0;n
<nb_max_retries
;n
++) {
47 if (nb_reconnect(cli
, tctx
, client
)) {
48 printf("[%d] Reconnected client %d\n", nbench_line_count
, client
);
52 printf("[%d] Failed to reconnect client %d\n", nbench_line_count
, client
);
56 /* run a test that simulates an approximate netbench client load */
57 static bool run_netbench(struct torture_context
*tctx
, struct smbcli_state
*cli
, int client
)
59 int torture_nprocs
= torture_setting_int(tctx
, "nprocs", 4);
65 double target_rate
= torture_setting_double(tctx
, "targetrate", 0);
68 if (target_rate
!= 0 && client
== 0) {
69 printf("Targeting %.4f MByte/sec\n", target_rate
);
72 nb_setup(cli
, client
);
74 if (torture_nprocs
== 1) {
76 NB_RETRY(torture_setup_dir(cli
, "\\clients"));
80 asprintf(&cname
, "client%d", client
+1);
82 f
= fopen(loadfile
, "r");
92 while (fgets(line
, sizeof(line
)-1, f
)) {
94 const char **params0
, **params
;
98 if ((strlen(line
) > 0) && line
[strlen(line
)-1] == '\n') {
99 line
[strlen(line
)-1] = 0;
102 all_string_sub(line
, "client1", cname
, sizeof(line
));
104 params
= params0
= const_str_list(
105 str_list_make_shell(NULL
, line
, " "));
106 i
= str_list_length(params
);
108 if (i
> 0 && isdigit(params
[0][0])) {
109 double targett
= strtod(params
[0], NULL
);
110 if (target_rate
!= 0) {
111 nbio_target_rate(target_rate
);
113 nbio_time_delay(targett
);
117 } else if (target_rate
!= 0) {
118 nbio_target_rate(target_rate
);
121 if (i
< 2 || params
[0][0] == '#') continue;
123 if (!strncmp(params
[0],"SMB", 3)) {
124 printf("ERROR: You are using a dbench 1 load file\n");
128 if (strncmp(params
[i
-1], "NT_STATUS_", 10) != 0 &&
129 strncmp(params
[i
-1], "0x", 2) != 0) {
130 printf("Badly formed status at line %d\n", nbench_line_count
);
135 /* accept numeric or string status codes */
136 if (strncmp(params
[i
-1], "0x", 2) == 0) {
137 status
= NT_STATUS(strtoul(params
[i
-1], NULL
, 16));
139 status
= nt_status_string_to_code(params
[i
-1]);
142 DEBUG(9,("run_netbench(%d): %s %s\n", client
, params
[0], params
[1]));
144 if (!strcmp(params
[0],"NTCreateX")) {
145 NB_RETRY(nb_createx(params
[1], ival(params
[2]), ival(params
[3]),
146 ival(params
[4]), status
));
147 } else if (!strcmp(params
[0],"Close")) {
148 NB_RETRY(nb_close(ival(params
[1]), status
));
149 } else if (!read_only
&& !strcmp(params
[0],"Rename")) {
150 NB_RETRY(nb_rename(params
[1], params
[2], status
, n
>0));
151 } else if (!read_only
&& !strcmp(params
[0],"Unlink")) {
152 NB_RETRY(nb_unlink(params
[1], ival(params
[2]), status
, n
>0));
153 } else if (!read_only
&& !strcmp(params
[0],"Deltree")) {
154 NB_RETRY(nb_deltree(params
[1], n
>0));
155 } else if (!read_only
&& !strcmp(params
[0],"Rmdir")) {
156 NB_RETRY(nb_rmdir(params
[1], status
, n
>0));
157 } else if (!read_only
&& !strcmp(params
[0],"Mkdir")) {
158 NB_RETRY(nb_mkdir(params
[1], status
, n
>0));
159 } else if (!strcmp(params
[0],"QUERY_PATH_INFORMATION")) {
160 NB_RETRY(nb_qpathinfo(params
[1], ival(params
[2]), status
));
161 } else if (!strcmp(params
[0],"QUERY_FILE_INFORMATION")) {
162 NB_RETRY(nb_qfileinfo(ival(params
[1]), ival(params
[2]), status
));
163 } else if (!strcmp(params
[0],"QUERY_FS_INFORMATION")) {
164 NB_RETRY(nb_qfsinfo(ival(params
[1]), status
));
165 } else if (!read_only
&& !strcmp(params
[0],"SET_FILE_INFORMATION")) {
166 NB_RETRY(nb_sfileinfo(ival(params
[1]), ival(params
[2]), status
));
167 } else if (!strcmp(params
[0],"FIND_FIRST")) {
168 NB_RETRY(nb_findfirst(params
[1], ival(params
[2]),
169 ival(params
[3]), ival(params
[4]), status
));
170 } else if (!read_only
&& !strcmp(params
[0],"WriteX")) {
171 NB_RETRY(nb_writex(ival(params
[1]),
172 ival(params
[2]), ival(params
[3]), ival(params
[4]),
174 } else if (!read_only
&& !strcmp(params
[0],"Write")) {
175 NB_RETRY(nb_write(ival(params
[1]),
176 ival(params
[2]), ival(params
[3]), ival(params
[4]),
178 } else if (!strcmp(params
[0],"LockX")) {
179 NB_RETRY(nb_lockx(ival(params
[1]),
180 ival(params
[2]), ival(params
[3]), status
));
181 } else if (!strcmp(params
[0],"UnlockX")) {
182 NB_RETRY(nb_unlockx(ival(params
[1]),
183 ival(params
[2]), ival(params
[3]), status
));
184 } else if (!strcmp(params
[0],"ReadX")) {
185 NB_RETRY(nb_readx(ival(params
[1]),
186 ival(params
[2]), ival(params
[3]), ival(params
[4]),
188 } else if (!strcmp(params
[0],"Flush")) {
189 NB_RETRY(nb_flush(ival(params
[1]), status
));
190 } else if (!strcmp(params
[0],"Sleep")) {
191 nb_sleep(ival(params
[1]), status
);
193 printf("[%d] Unknown operation %s\n", nbench_line_count
, params
[0]);
196 if (n
> nb_max_retries
) {
197 printf("Maximum reconnect retries reached for op '%s'\n", params
[0]);
201 talloc_free(params0
);
203 if (nb_tick()) goto done
;
212 if (!read_only
&& torture_nprocs
== 1) {
213 smbcli_deltree(cli
->tree
, "\\clients");
215 if (!torture_close_connection(cli
)) {
223 /* run a test that simulates an approximate netbench client load */
224 bool torture_nbench(struct torture_context
*torture
)
227 int torture_nprocs
= torture_setting_int(torture
, "nprocs", 4);
228 struct smbcli_state
*cli
;
231 read_only
= torture_setting_bool(torture
, "readonly", false);
233 nb_max_retries
= torture_setting_int(torture
, "nretries", 1);
235 p
= torture_setting_string(torture
, "timelimit", NULL
);
240 warmup
= timelimit
/ 20;
242 loadfile
= torture_setting_string(torture
, "loadfile", NULL
);
243 if (!loadfile
|| !*loadfile
) {
244 loadfile
= "client.txt";
247 if (torture_nprocs
> 1) {
248 if (!torture_open_connection(&cli
, torture
, 0)) {
252 if (!read_only
&& !torture_setup_dir(cli
, "\\clients")) {
257 nbio_shmem(torture_nprocs
, timelimit
, warmup
);
259 printf("Running for %d seconds with load '%s' and warmup %d secs\n",
260 timelimit
, loadfile
, warmup
);
262 /* we need to reset SIGCHLD here as the name resolution
263 library may have changed it. We rely on correct signals
264 from childs in the main torture code which reaps
265 children. This is why smbtorture BENCH-NBENCH was sometimes
267 signal(SIGCHLD
, SIG_DFL
);
270 signal(SIGALRM
, nb_alarm
);
272 torture_create_procs(torture
, run_netbench
, &correct
);
275 if (!read_only
&& torture_nprocs
> 1) {
276 smbcli_deltree(cli
->tree
, "\\clients");
279 printf("\nThroughput %g MB/sec\n", nbio_result());
283 NTSTATUS
torture_nbench_init(void)
285 struct torture_suite
*suite
= torture_suite_create(
286 talloc_autofree_context(), "bench");
288 torture_suite_add_simple_test(suite
, "nbench", torture_nbench
);
290 suite
->description
= talloc_strdup(suite
, "Benchmarks");
292 torture_register_suite(suite
);