Fix bug 6546: Avoid accessing buf[-1] if NUL byte comes from fgets
[Samba/kamenim.git] / source4 / torture / nbench / nbench.c
blob05c889d1b7d34587bc91c1bbe3f0d42e29b6b10e
1 /*
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/>.
20 #include "includes.h"
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;
31 static int warmup;
32 static const char *loadfile;
33 static int read_only;
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)
44 int n;
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);
49 return;
52 printf("[%d] Failed to reconnect client %d\n", nbench_line_count, client);
53 nb_exit(1);
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);
60 int i;
61 char line[1024];
62 char *cname;
63 FILE *f;
64 bool correct = true;
65 double target_rate = torture_setting_double(tctx, "targetrate", 0);
66 int n;
68 if (target_rate != 0 && client == 0) {
69 printf("Targetting %.4f MByte/sec\n", target_rate);
72 nb_setup(cli, client);
74 if (torture_nprocs == 1) {
75 if (!read_only) {
76 NB_RETRY(torture_setup_dir(cli, "\\clients"));
80 asprintf(&cname, "client%d", client+1);
82 f = fopen(loadfile, "r");
84 if (!f) {
85 perror(loadfile);
86 return false;
89 again:
90 nbio_time_reset();
92 while (fgets(line, sizeof(line)-1, f)) {
93 NTSTATUS status;
94 const char **params0, **params;
96 nbench_line_count++;
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 = str_list_make_shell(NULL, line, " ");
105 i = str_list_length(params);
107 if (i > 0 && isdigit(params[0][0])) {
108 double targett = strtod(params[0], NULL);
109 if (target_rate != 0) {
110 nbio_target_rate(target_rate);
111 } else {
112 nbio_time_delay(targett);
114 params++;
115 i--;
116 } else if (target_rate != 0) {
117 nbio_target_rate(target_rate);
120 if (i < 2 || params[0][0] == '#') continue;
122 if (!strncmp(params[0],"SMB", 3)) {
123 printf("ERROR: You are using a dbench 1 load file\n");
124 nb_exit(1);
127 if (strncmp(params[i-1], "NT_STATUS_", 10) != 0 &&
128 strncmp(params[i-1], "0x", 2) != 0) {
129 printf("Badly formed status at line %d\n", nbench_line_count);
130 talloc_free(params);
131 continue;
134 /* accept numeric or string status codes */
135 if (strncmp(params[i-1], "0x", 2) == 0) {
136 status = NT_STATUS(strtoul(params[i-1], NULL, 16));
137 } else {
138 status = nt_status_string_to_code(params[i-1]);
141 DEBUG(9,("run_netbench(%d): %s %s\n", client, params[0], params[1]));
143 if (!strcmp(params[0],"NTCreateX")) {
144 NB_RETRY(nb_createx(params[1], ival(params[2]), ival(params[3]),
145 ival(params[4]), status));
146 } else if (!strcmp(params[0],"Close")) {
147 NB_RETRY(nb_close(ival(params[1]), status));
148 } else if (!read_only && !strcmp(params[0],"Rename")) {
149 NB_RETRY(nb_rename(params[1], params[2], status, n>0));
150 } else if (!read_only && !strcmp(params[0],"Unlink")) {
151 NB_RETRY(nb_unlink(params[1], ival(params[2]), status, n>0));
152 } else if (!read_only && !strcmp(params[0],"Deltree")) {
153 NB_RETRY(nb_deltree(params[1], n>0));
154 } else if (!read_only && !strcmp(params[0],"Rmdir")) {
155 NB_RETRY(nb_rmdir(params[1], status, n>0));
156 } else if (!read_only && !strcmp(params[0],"Mkdir")) {
157 NB_RETRY(nb_mkdir(params[1], status, n>0));
158 } else if (!strcmp(params[0],"QUERY_PATH_INFORMATION")) {
159 NB_RETRY(nb_qpathinfo(params[1], ival(params[2]), status));
160 } else if (!strcmp(params[0],"QUERY_FILE_INFORMATION")) {
161 NB_RETRY(nb_qfileinfo(ival(params[1]), ival(params[2]), status));
162 } else if (!strcmp(params[0],"QUERY_FS_INFORMATION")) {
163 NB_RETRY(nb_qfsinfo(ival(params[1]), status));
164 } else if (!read_only && !strcmp(params[0],"SET_FILE_INFORMATION")) {
165 NB_RETRY(nb_sfileinfo(ival(params[1]), ival(params[2]), status));
166 } else if (!strcmp(params[0],"FIND_FIRST")) {
167 NB_RETRY(nb_findfirst(params[1], ival(params[2]),
168 ival(params[3]), ival(params[4]), status));
169 } else if (!read_only && !strcmp(params[0],"WriteX")) {
170 NB_RETRY(nb_writex(ival(params[1]),
171 ival(params[2]), ival(params[3]), ival(params[4]),
172 status));
173 } else if (!read_only && !strcmp(params[0],"Write")) {
174 NB_RETRY(nb_write(ival(params[1]),
175 ival(params[2]), ival(params[3]), ival(params[4]),
176 status));
177 } else if (!strcmp(params[0],"LockX")) {
178 NB_RETRY(nb_lockx(ival(params[1]),
179 ival(params[2]), ival(params[3]), status));
180 } else if (!strcmp(params[0],"UnlockX")) {
181 NB_RETRY(nb_unlockx(ival(params[1]),
182 ival(params[2]), ival(params[3]), status));
183 } else if (!strcmp(params[0],"ReadX")) {
184 NB_RETRY(nb_readx(ival(params[1]),
185 ival(params[2]), ival(params[3]), ival(params[4]),
186 status));
187 } else if (!strcmp(params[0],"Flush")) {
188 NB_RETRY(nb_flush(ival(params[1]), status));
189 } else if (!strcmp(params[0],"Sleep")) {
190 nb_sleep(ival(params[1]), status);
191 } else {
192 printf("[%d] Unknown operation %s\n", nbench_line_count, params[0]);
195 if (n > nb_max_retries) {
196 printf("Maximum reconnect retries reached for op '%s'\n", params[0]);
197 nb_exit(1);
200 talloc_free(params0);
202 if (nb_tick()) goto done;
205 rewind(f);
206 goto again;
208 done:
209 fclose(f);
211 if (!read_only && torture_nprocs == 1) {
212 smbcli_deltree(cli->tree, "\\clients");
214 if (!torture_close_connection(cli)) {
215 correct = false;
218 return correct;
222 /* run a test that simulates an approximate netbench client load */
223 bool torture_nbench(struct torture_context *torture)
225 bool correct = true;
226 int torture_nprocs = torture_setting_int(torture, "nprocs", 4);
227 struct smbcli_state *cli;
228 const char *p;
230 read_only = torture_setting_bool(torture, "readonly", false);
232 nb_max_retries = torture_setting_int(torture, "nretries", 1);
234 p = torture_setting_string(torture, "timelimit", NULL);
235 if (p && *p) {
236 timelimit = atoi(p);
239 warmup = timelimit / 20;
241 loadfile = torture_setting_string(torture, "loadfile", NULL);
242 if (!loadfile || !*loadfile) {
243 loadfile = "client.txt";
246 if (torture_nprocs > 1) {
247 if (!torture_open_connection(&cli, torture, 0)) {
248 return false;
251 if (!read_only && !torture_setup_dir(cli, "\\clients")) {
252 return false;
256 nbio_shmem(torture_nprocs, timelimit, warmup);
258 printf("Running for %d seconds with load '%s' and warmup %d secs\n",
259 timelimit, loadfile, warmup);
261 /* we need to reset SIGCHLD here as the name resolution
262 library may have changed it. We rely on correct signals
263 from childs in the main torture code which reaps
264 children. This is why smbtorture BENCH-NBENCH was sometimes
265 failing */
266 signal(SIGCHLD, SIG_DFL);
269 signal(SIGALRM, nb_alarm);
270 alarm(1);
271 torture_create_procs(torture, run_netbench, &correct);
272 alarm(0);
274 if (!read_only && torture_nprocs > 1) {
275 smbcli_deltree(cli->tree, "\\clients");
278 printf("\nThroughput %g MB/sec\n", nbio_result());
279 return correct;
282 NTSTATUS torture_nbench_init(void)
284 struct torture_suite *suite =
285 torture_suite_create(
286 talloc_autofree_context(),
287 "BENCH");
289 torture_suite_add_simple_test(suite, "NBENCH", torture_nbench);
291 suite->description = talloc_strdup(suite, "Benchmarks");
293 torture_register_suite(suite);
294 return NT_STATUS_OK;