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);
69 if (target_rate != 0 && client == 0) {
70 printf("Targeting %.4f MByte/sec\n", target_rate);
73 nb_setup(cli, client);
75 if (torture_nprocs == 1) {
77 NB_RETRY(torture_setup_dir(cli, "\\clients"));
81 ret = asprintf(&cname, "client%d", client+1);
86 f = fopen(loadfile, "r");
96 while (fgets(line, sizeof(line)-1, f)) {
98 const char **params0, **params;
102 if ((strlen(line) > 0) && line[strlen(line)-1] == '\n') {
103 line[strlen(line)-1] = 0;
106 all_string_sub(line, "client1", cname, sizeof(line));
108 params = params0 = const_str_list(
109 str_list_make_shell(NULL, line, " "));
110 i = str_list_length(params);
112 if (i > 0 && isdigit(params[0][0])) {
113 double targett = strtod(params[0], NULL);
114 if (target_rate != 0) {
115 nbio_target_rate(target_rate);
117 nbio_time_delay(targett);
121 } else if (target_rate != 0) {
122 nbio_target_rate(target_rate);
125 if (i < 2 || params[0][0] == '#') continue;
127 if (!strncmp(params[0],"SMB", 3)) {
128 printf("ERROR: You are using a dbench 1 load file\n");
132 if (strncmp(params[i-1], "NT_STATUS_", 10) != 0 &&
133 strncmp(params[i-1], "0x", 2) != 0) {
134 printf("Badly formed status at line %d\n", nbench_line_count);
139 /* accept numeric or string status codes */
140 if (strncmp(params[i-1], "0x", 2) == 0) {
141 status = NT_STATUS(strtoul(params[i-1], NULL, 16));
143 status = nt_status_string_to_code(params[i-1]);
146 DEBUG(9,("run_netbench(%d): %s %s\n", client, params[0], params[1]));
148 if (!strcmp(params[0],"NTCreateX")) {
149 NB_RETRY(nb_createx(params[1], ival(params[2]), ival(params[3]),
150 ival(params[4]), status));
151 } else if (!strcmp(params[0],"Close")) {
152 NB_RETRY(nb_close(ival(params[1]), status));
153 } else if (!read_only && !strcmp(params[0],"Rename")) {
154 NB_RETRY(nb_rename(params[1], params[2], status, n>0));
155 } else if (!read_only && !strcmp(params[0],"Unlink")) {
156 NB_RETRY(nb_unlink(params[1], ival(params[2]), status, n>0));
157 } else if (!read_only && !strcmp(params[0],"Deltree")) {
158 NB_RETRY(nb_deltree(params[1], n>0));
159 } else if (!read_only && !strcmp(params[0],"Rmdir")) {
160 NB_RETRY(nb_rmdir(params[1], status, n>0));
161 } else if (!read_only && !strcmp(params[0],"Mkdir")) {
162 NB_RETRY(nb_mkdir(params[1], status, n>0));
163 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
164 NB_RETRY(nb_qpathinfo(params[1], ival(params[2]), status));
165 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
166 NB_RETRY(nb_qfileinfo(ival(params[1]), ival(params[2]), status));
167 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
168 NB_RETRY(nb_qfsinfo(ival(params[1]), status));
169 } else if (!read_only && !strcmp(params[0],"SET_FILE_INFORMATION")) {
170 NB_RETRY(nb_sfileinfo(ival(params[1]), ival(params[2]), status));
171 } else if (!strcmp(params[0],"FIND_FIRST")) {
172 NB_RETRY(nb_findfirst(params[1], ival(params[2]),
173 ival(params[3]), ival(params[4]), status));
174 } else if (!read_only && !strcmp(params[0],"WriteX")) {
175 NB_RETRY(nb_writex(ival(params[1]),
176 ival(params[2]), ival(params[3]), ival(params[4]),
178 } else if (!read_only && !strcmp(params[0],"Write")) {
179 NB_RETRY(nb_write(ival(params[1]),
180 ival(params[2]), ival(params[3]), ival(params[4]),
182 } else if (!strcmp(params[0],"LockX")) {
183 NB_RETRY(nb_lockx(ival(params[1]),
184 ival(params[2]), ival(params[3]), status));
185 } else if (!strcmp(params[0],"UnlockX")) {
186 NB_RETRY(nb_unlockx(ival(params[1]),
187 ival(params[2]), ival(params[3]), status));
188 } else if (!strcmp(params[0],"ReadX")) {
189 NB_RETRY(nb_readx(ival(params[1]),
190 ival(params[2]), ival(params[3]), ival(params[4]),
192 } else if (!strcmp(params[0],"Flush")) {
193 NB_RETRY(nb_flush(ival(params[1]), status));
194 } else if (!strcmp(params[0],"Sleep")) {
195 nb_sleep(ival(params[1]), status);
197 printf("[%d] Unknown operation %s\n", nbench_line_count, params[0]);
200 if (n > nb_max_retries) {
201 printf("Maximum reconnect retries reached for op '%s'\n", params[0]);
205 talloc_free(params0);
207 if (nb_tick()) goto done;
216 if (!read_only && torture_nprocs == 1) {
217 smbcli_deltree(cli->tree, "\\clients");
219 if (!torture_close_connection(cli)) {
227 /* run a test that simulates an approximate netbench client load */
228 bool torture_nbench(struct torture_context *torture)
231 int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
232 struct smbcli_state *cli;
235 read_only = torture_setting_bool(torture, "readonly", false);
237 nb_max_retries = torture_setting_int(torture, "nretries", 1);
239 p = torture_setting_string(torture, "timelimit", NULL);
244 warmup = timelimit / 20;
246 loadfile = torture_setting_string(torture, "loadfile", NULL);
247 if (!loadfile || !*loadfile) {
248 loadfile = "client.txt";
251 if (torture_nprocs > 1) {
252 if (!torture_open_connection(&cli, torture, 0)) {
256 if (!read_only && !torture_setup_dir(cli, "\\clients")) {
261 nbio_shmem(torture_nprocs, timelimit, warmup);
263 printf("Running for %d seconds with load '%s' and warmup %d secs\n",
264 timelimit, loadfile, warmup);
266 /* we need to reset SIGCHLD here as the name resolution
267 library may have changed it. We rely on correct signals
268 from childs in the main torture code which reaps
269 children. This is why smbtorture BENCH-NBENCH was sometimes
271 signal(SIGCHLD, SIG_DFL);
274 signal(SIGALRM, nb_alarm);
276 torture_create_procs(torture, run_netbench, &correct);
279 if (!read_only && torture_nprocs > 1) {
280 smbcli_deltree(cli->tree, "\\clients");
283 printf("\nThroughput %g MB/sec\n", nbio_result());
287 NTSTATUS torture_nbench_init(void)
289 struct torture_suite *suite = torture_suite_create(
290 talloc_autofree_context(), "bench");
292 torture_suite_add_simple_test(suite, "nbench", torture_nbench);
294 suite->description = talloc_strdup(suite, "Benchmarks");
296 torture_register_suite(suite);