2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2007
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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "torture/torture.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "system/time.h"
27 #include "system/filesys.h"
28 #include "libcli/libcli.h"
29 #include "torture/util.h"
30 #include "lib/events/events.h"
31 #include "lib/cmdline/popt_common.h"
33 #define BASEDIR "\\benchopen"
36 static int open_failed;
37 static int open_retries;
40 struct benchopen_state {
41 struct smbcli_state *cli;
45 BOOL waiting_open, waiting_close;
46 union smb_open open_parms;
47 union smb_close close_parms;
48 struct smbcli_request *req_open;
49 struct smbcli_request *req_close;
52 static void open_completed(struct smbcli_request *req);
53 static void close_completed(struct smbcli_request *req);
56 static void next_open(struct benchopen_state *state)
60 state->file_num = (state->file_num+1) % (nprocs+1);
61 state->open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
62 state->open_parms.ntcreatex.in.flags = 0;
63 state->open_parms.ntcreatex.in.root_fid = 0;
64 state->open_parms.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
65 state->open_parms.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
66 state->open_parms.ntcreatex.in.alloc_size = 0;
67 state->open_parms.ntcreatex.in.share_access = 0;
68 state->open_parms.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
69 state->open_parms.ntcreatex.in.create_options = 0;
70 state->open_parms.ntcreatex.in.impersonation = 0;
71 state->open_parms.ntcreatex.in.security_flags = 0;
72 state->open_parms.ntcreatex.in.fname = fnames[state->file_num];
74 state->req_open = smb_raw_open_send(state->cli->tree, &state->open_parms);
75 state->req_open->async.fn = open_completed;
76 state->req_open->async.private = state;
77 state->waiting_open = True;
79 if (state->fnum == -1) {
83 state->close_parms.close.level = RAW_CLOSE_CLOSE;
84 state->close_parms.close.in.file.fnum = state->fnum;
85 state->close_parms.close.in.write_time = 0;
87 state->req_close = smb_raw_close_send(state->cli->tree, &state->close_parms);
88 state->req_close->async.fn = close_completed;
89 state->req_close->async.private = state;
90 state->waiting_close = True;
94 called when a open completes
96 static void open_completed(struct smbcli_request *req)
98 struct benchopen_state *state = (struct benchopen_state *)req->async.private;
99 TALLOC_CTX *tmp_ctx = talloc_new(state->cli);
102 status = smb_raw_open_recv(req, tmp_ctx, &state->open_parms);
104 talloc_free(tmp_ctx);
106 state->req_open = NULL;
108 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
110 state->req_open = smb_raw_open_send(state->cli->tree, &state->open_parms);
111 state->req_open->async.fn = open_completed;
112 state->req_open->async.private = state;
116 if (!NT_STATUS_IS_OK(status)) {
118 DEBUG(0,("open failed - %s\n", nt_errstr(status)));
122 state->fnum = state->open_parms.ntcreatex.out.file.fnum;
123 state->waiting_open = False;
125 if (!state->waiting_close) {
131 called when a close completes
133 static void close_completed(struct smbcli_request *req)
135 struct benchopen_state *state = (struct benchopen_state *)req->async.private;
136 NTSTATUS status = smbcli_request_simple_recv(req);
138 state->req_close = NULL;
140 if (!NT_STATUS_IS_OK(status)) {
142 DEBUG(0,("close failed - %s\n", nt_errstr(status)));
146 state->waiting_close = False;
148 if (!state->waiting_open) {
156 BOOL torture_bench_open(struct torture_context *torture)
159 TALLOC_CTX *mem_ctx = talloc_new(torture);
161 int timelimit = torture_setting_int(torture, "timelimit", 10);
163 struct event_context *ev = event_context_find(mem_ctx);
164 struct benchopen_state *state;
165 int total = 0, loops=0, minops=0;
167 nprocs = lp_parm_int(-1, "torture", "nprocs", 4);
169 state = talloc_zero_array(mem_ctx, struct benchopen_state, nprocs);
171 printf("Opening %d connections\n", nprocs);
172 for (i=0;i<nprocs;i++) {
173 if (!torture_open_connection_ev(&state[i].cli, i, ev)) {
176 talloc_steal(mem_ctx, state);
179 if (!torture_setup_dir(state[0].cli, BASEDIR)) {
183 fnames = talloc_array(mem_ctx, char *, nprocs+1);
184 for (i=0;i<nprocs+1;i++) {
185 fnames[i] = talloc_asprintf(fnames, "%s\\file%d.dat", BASEDIR, i);
188 for (i=0;i<nprocs;i++) {
190 state[i].file_num = i;
191 next_open(&state[i]);
194 tv = timeval_current();
196 printf("Running for %d seconds\n", timelimit);
197 while (timeval_elapsed(&tv) < timelimit) {
201 for (i=0;i<nprocs;i++) {
202 total += state[i].count;
206 DEBUG(0,("open failed after %d opens\n", total));
210 if (loops++ % 1000 != 0) continue;
212 printf("%.2f ops/second (%d retries)\r",
213 total/timeval_elapsed(&tv), open_retries);
217 printf("%.2f ops/second (%d retries)\n",
218 total/timeval_elapsed(&tv), open_retries);
219 minops = state[0].count;
220 for (i=0;i<nprocs;i++) {
221 printf("[%d] %u ops\n", i, state[i].count);
222 if (state[i].count < minops) minops = state[i].count;
224 if (minops < 0.5*total/nprocs) {
225 printf("Failed: unbalanced open\n");
229 for (i=0;i<nprocs;i++) {
230 talloc_free(state[i].req_open);
231 talloc_free(state[i].req_close);
232 smb_raw_exit(state[i].cli->session);
235 smbcli_deltree(state[0].cli->tree, BASEDIR);
236 talloc_free(mem_ctx);
240 for (i=0;i<nprocs;i++) {
241 talloc_free(state[i].req_open);
242 talloc_free(state[i].req_close);
243 smb_raw_exit(state[i].cli->session);
245 smbcli_deltree(state[0].cli->tree, BASEDIR);
246 talloc_free(mem_ctx);