diff options
-rw-r--r-- | source4/torture/config.mk | 1 | ||||
-rw-r--r-- | source4/torture/raw/lockbench.c | 196 | ||||
-rw-r--r-- | source4/torture/raw/raw.c | 5 |
3 files changed, 200 insertions, 2 deletions
diff --git a/source4/torture/config.mk b/source4/torture/config.mk index de74103b46..01f095e146 100644 --- a/source4/torture/config.mk +++ b/source4/torture/config.mk @@ -78,6 +78,7 @@ OBJ_FILES = \ raw/context.o \ raw/write.o \ raw/lock.o \ + raw/lockbench.o \ raw/rename.o \ raw/eas.o \ raw/streams.o \ diff --git a/source4/torture/raw/lockbench.c b/source4/torture/raw/lockbench.c new file mode 100644 index 0000000000..04a3f92c93 --- /dev/null +++ b/source4/torture/raw/lockbench.c @@ -0,0 +1,196 @@ +/* + Unix SMB/CIFS implementation. + + locking benchmark + + Copyright (C) Andrew Tridgell 2006 + + 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 CHECK_STATUS(status, correct) do { \ + if (!NT_STATUS_EQUAL(status, correct)) { \ + printf("(%s) Incorrect status %s - should be %s\n", \ + __location__, nt_errstr(status), nt_errstr(correct)); \ + goto failed; \ + }} while (0) + +#define BASEDIR "\\benchlock" +#define FNAME BASEDIR "\\lock.dat" + +static int nprocs; +static int lock_failed; + +struct benchlock_state { + struct smbcli_state *cli; + int fnum; + int offset; + int count; + union smb_lock io; + struct smb_lock_entry lock[2]; + struct smbcli_request *req; +}; + +static void lock_completion(struct smbcli_request *); + +/* + send the next lock request +*/ +static void lock_send(struct benchlock_state *state) +{ + state->io.lockx.in.file.fnum = state->fnum; + state->io.lockx.in.ulock_cnt = 1; + state->lock[0].pid = state->cli->session->pid; + state->lock[1].pid = state->cli->session->pid; + state->lock[0].offset = state->offset; + state->lock[1].offset = (state->offset+1)%nprocs; + state->req = smb_raw_lock_send(state->cli->tree, &state->io); + if (state->req == NULL) { + DEBUG(0,("Failed to setup lock\n")); + lock_failed++; + } + state->req->async.private = state; + state->req->async.fn = lock_completion; + state->offset = (state->offset+1)%nprocs; +} + +/* + called when a lock completes +*/ +static void lock_completion(struct smbcli_request *req) +{ + struct benchlock_state *state = (struct benchlock_state *)req->async.private; + NTSTATUS status = smbcli_request_simple_recv(req); + if (!NT_STATUS_IS_OK(status)) { + lock_failed++; + DEBUG(0,("Lock failed - %s\n", nt_errstr(status))); + } else { + state->count++; + lock_send(state); + } +} + +/* + benchmark locking calls +*/ +BOOL torture_bench_lock(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 benchlock_state *state; + int total = 0, loops=0; + NTSTATUS status; + + nprocs = lp_parm_int(-1, "torture", "nprocs", 4); + + state = talloc_zero_array(mem_ctx, struct benchlock_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; + } + + for (i=0;i<nprocs;i++) { + state[i].fnum = smbcli_open(state[i].cli->tree, + FNAME, + O_RDWR|O_CREAT, DENY_NONE); + if (state[i].fnum == -1) { + printf("Failed to open %s on connection %d\n", FNAME, i); + goto failed; + } + + state[i].io.lockx.level = RAW_LOCK_LOCKX; + state[i].io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; + state[i].io.lockx.in.timeout = 100000; + state[i].io.lockx.in.ulock_cnt = 0; + state[i].io.lockx.in.lock_cnt = 1; + state[i].lock[0].count = 1; + state[i].lock[1].count = 1; + state[i].io.lockx.in.locks = &state[i].lock[0]; + + state[i].offset = i; + state[i].io.lockx.in.file.fnum = state[i].fnum; + state[i].lock[0].offset = state[i].offset; + state[i].lock[0].pid = state[i].cli->session->pid; + status = smb_raw_lock(state[i].cli->tree, &state[i].io); + CHECK_STATUS(status, NT_STATUS_OK); + } + + for (i=0;i<nprocs;i++) { + lock_send(&state[i]); + } + + tv = timeval_current(); + + printf("Running for %d seconds\n", timelimit); + while (timeval_elapsed(&tv) < timelimit) { + event_loop_once(ev); + + if (lock_failed) { + DEBUG(0,("locking failed\n")); + goto failed; + } + + if (loops++ % 10 != 0) continue; + + total = 0; + for (i=0;i<nprocs;i++) { + total += state[i].count; + } + printf("%.2f ops/second\r", total/timeval_elapsed(&tv)); + fflush(stdout); + } + + printf("%.2f ops/second\n", total/timeval_elapsed(&tv)); + + for (i=0;i<nprocs;i++) { + talloc_free(state[i].req); + 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); + 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 411430a565..817105614e 100644 --- a/source4/torture/raw/raw.c +++ b/source4/torture/raw/raw.c @@ -26,10 +26,11 @@ NTSTATUS torture_raw_init(void) { struct torture_suite *suite = torture_suite_create( - talloc_autofree_context(), - "RAW"); + talloc_autofree_context(), + "RAW"); /* 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, "QFSINFO", torture_raw_qfsinfo); torture_suite_add_simple_test(suite, "QFILEINFO", torture_raw_qfileinfo); torture_suite_add_simple_test(suite, "SFILEINFO", torture_raw_sfileinfo); |