diff options
Diffstat (limited to 'source4/torture')
-rw-r--r-- | source4/torture/config.mk | 1 | ||||
-rw-r--r-- | source4/torture/raw/openbench.c | 248 | ||||
-rw-r--r-- | source4/torture/raw/raw.c | 1 |
3 files changed, 250 insertions, 0 deletions
diff --git a/source4/torture/config.mk b/source4/torture/config.mk index 640e79cd95..d66c57b18e 100644 --- a/source4/torture/config.mk +++ b/source4/torture/config.mk @@ -78,6 +78,7 @@ OBJ_FILES = \ raw/write.o \ raw/lock.o \ raw/lockbench.o \ + raw/openbench.o \ raw/rename.o \ raw/eas.o \ raw/streams.o \ diff --git a/source4/torture/raw/openbench.c b/source4/torture/raw/openbench.c new file mode 100644 index 0000000000..a7f95d7c53 --- /dev/null +++ b/source4/torture/raw/openbench.c @@ -0,0 +1,248 @@ +/* + Unix SMB/CIFS implementation. + + open benchmark + + Copyright (C) Andrew Tridgell 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include "torture/torture.h" +#include "libcli/raw/libcliraw.h" +#include "system/time.h" +#include "system/filesys.h" +#include "libcli/libcli.h" +#include "torture/util.h" +#include "lib/events/events.h" +#include "lib/cmdline/popt_common.h" + +#define BASEDIR "\\benchopen" + +static int nprocs; +static int open_failed; +static int open_retries; +static char **fnames; + +struct benchopen_state { + struct smbcli_state *cli; + int fnum; + int file_num; + int count; + BOOL waiting_open, waiting_close; + union smb_open open_parms; + union smb_close close_parms; + struct smbcli_request *req_open; + struct smbcli_request *req_close; +}; + +static void open_completed(struct smbcli_request *req); +static void close_completed(struct smbcli_request *req); + + +static void next_open(struct benchopen_state *state) +{ + state->count++; + + state->file_num = (state->file_num+1) % (nprocs+1); + state->open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX; + state->open_parms.ntcreatex.in.flags = 0; + state->open_parms.ntcreatex.in.root_fid = 0; + state->open_parms.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL; + state->open_parms.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL; + state->open_parms.ntcreatex.in.alloc_size = 0; + state->open_parms.ntcreatex.in.share_access = 0; + state->open_parms.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF; + state->open_parms.ntcreatex.in.create_options = 0; + state->open_parms.ntcreatex.in.impersonation = 0; + state->open_parms.ntcreatex.in.security_flags = 0; + state->open_parms.ntcreatex.in.fname = fnames[state->file_num]; + + state->req_open = smb_raw_open_send(state->cli->tree, &state->open_parms); + state->req_open->async.fn = open_completed; + state->req_open->async.private = state; + state->waiting_open = True; + + if (state->fnum == -1) { + return; + } + + state->close_parms.close.level = RAW_CLOSE_CLOSE; + state->close_parms.close.in.file.fnum = state->fnum; + state->close_parms.close.in.write_time = 0; + + state->req_close = smb_raw_close_send(state->cli->tree, &state->close_parms); + state->req_close->async.fn = close_completed; + state->req_close->async.private = state; + state->waiting_close = True; +} + +/* + called when a open completes +*/ +static void open_completed(struct smbcli_request *req) +{ + struct benchopen_state *state = (struct benchopen_state *)req->async.private; + TALLOC_CTX *tmp_ctx = talloc_new(state->cli); + NTSTATUS status; + + status = smb_raw_open_recv(req, tmp_ctx, &state->open_parms); + + talloc_free(tmp_ctx); + + state->req_open = NULL; + + if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) { + open_retries++; + state->req_open = smb_raw_open_send(state->cli->tree, &state->open_parms); + state->req_open->async.fn = open_completed; + state->req_open->async.private = state; + return; + } + + if (!NT_STATUS_IS_OK(status)) { + open_failed++; + DEBUG(0,("open failed - %s\n", nt_errstr(status))); + return; + } + + state->fnum = state->open_parms.ntcreatex.out.file.fnum; + state->waiting_open = False; + + if (!state->waiting_close) { + next_open(state); + } +} + +/* + called when a close completes +*/ +static void close_completed(struct smbcli_request *req) +{ + struct benchopen_state *state = (struct benchopen_state *)req->async.private; + NTSTATUS status = smbcli_request_simple_recv(req); + + state->req_close = NULL; + + if (!NT_STATUS_IS_OK(status)) { + open_failed++; + DEBUG(0,("close failed - %s\n", nt_errstr(status))); + return; + } + + state->waiting_close = False; + + if (!state->waiting_open) { + next_open(state); + } +} + +/* + benchmark open calls +*/ +BOOL torture_bench_open(struct torture_context *torture) +{ + BOOL ret = True; + TALLOC_CTX *mem_ctx = talloc_new(torture); + int i; + int timelimit = torture_setting_int(torture, "timelimit", 10); + struct timeval tv; + struct event_context *ev = event_context_find(mem_ctx); + struct benchopen_state *state; + int total = 0, loops=0, minops=0; + + nprocs = lp_parm_int(-1, "torture", "nprocs", 4); + + state = talloc_zero_array(mem_ctx, struct benchopen_state, nprocs); + + printf("Opening %d connections\n", nprocs); + for (i=0;i<nprocs;i++) { + if (!torture_open_connection_ev(&state[i].cli, i, ev)) { + return False; + } + talloc_steal(mem_ctx, state); + } + + if (!torture_setup_dir(state[0].cli, BASEDIR)) { + goto failed; + } + + fnames = talloc_array(mem_ctx, char *, nprocs+1); + for (i=0;i<nprocs+1;i++) { + fnames[i] = talloc_asprintf(fnames, "%s\\file%d.dat", BASEDIR, i); + } + + for (i=0;i<nprocs;i++) { + state[i].fnum = -1; + state[i].file_num = i; + next_open(&state[i]); + } + + tv = timeval_current(); + + printf("Running for %d seconds\n", timelimit); + while (timeval_elapsed(&tv) < timelimit) { + event_loop_once(ev); + + total = 0; + for (i=0;i<nprocs;i++) { + total += state[i].count; + } + + if (open_failed) { + DEBUG(0,("open failed after %d opens\n", total)); + goto failed; + } + + if (loops++ % 1000 != 0) continue; + + printf("%.2f ops/second (%d retries)\r", + total/timeval_elapsed(&tv), open_retries); + fflush(stdout); + } + + printf("%.2f ops/second (%d retries)\n", + total/timeval_elapsed(&tv), open_retries); + minops = state[0].count; + for (i=0;i<nprocs;i++) { + printf("[%d] %u ops\n", i, state[i].count); + if (state[i].count < minops) minops = state[i].count; + } + if (minops < 0.5*total/nprocs) { + printf("Failed: unbalanced open\n"); + goto failed; + } + + for (i=0;i<nprocs;i++) { + talloc_free(state[i].req_open); + talloc_free(state[i].req_close); + smb_raw_exit(state[i].cli->session); + } + + smbcli_deltree(state[0].cli->tree, BASEDIR); + talloc_free(mem_ctx); + return ret; + +failed: + for (i=0;i<nprocs;i++) { + talloc_free(state[i].req_open); + talloc_free(state[i].req_close); + smb_raw_exit(state[i].cli->session); + } + smbcli_deltree(state[0].cli->tree, BASEDIR); + talloc_free(mem_ctx); + return False; +} diff --git a/source4/torture/raw/raw.c b/source4/torture/raw/raw.c index ee74d6b84b..eb89193f47 100644 --- a/source4/torture/raw/raw.c +++ b/source4/torture/raw/raw.c @@ -31,6 +31,7 @@ NTSTATUS torture_raw_init(void) /* RAW smb tests */ torture_suite_add_simple_test(suite, "BENCH-OPLOCK", torture_bench_oplock); torture_suite_add_simple_test(suite, "BENCH-LOCK", torture_bench_lock); + torture_suite_add_simple_test(suite, "BENCH-OPEN", torture_bench_open); torture_suite_add_simple_test(suite, "QFSINFO", torture_raw_qfsinfo); torture_suite_add_simple_test(suite, "QFILEINFO", torture_raw_qfileinfo); torture_suite_add_simple_test(suite, "SFILEINFO", torture_raw_sfileinfo); |