From cf0cdf5171d4e0ca01b697155ceb04ffc2863231 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 14 May 2007 03:49:42 +0000 Subject: [PATCH] r22837: make RAW-BENCH-LOCK reconnect asynchronously when one of its servers goges away --- source/torture/raw/lockbench.c | 150 +++++++++++++++++++++++++-------- 1 file changed, 116 insertions(+), 34 deletions(-) diff --git a/source/torture/raw/lockbench.c b/source/torture/raw/lockbench.c index 1621139aa76..705ab4d6912 100644 --- a/source/torture/raw/lockbench.c +++ b/source/torture/raw/lockbench.c @@ -29,6 +29,8 @@ #include "torture/util.h" #include "lib/events/events.h" #include "lib/cmdline/popt_common.h" +#include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" #define CHECK_STATUS(status, correct) do { \ if (!NT_STATUS_EQUAL(status, correct)) { \ @@ -45,7 +47,8 @@ static int lock_failed; struct benchlock_state { struct event_context *ev; - struct smbcli_state *cli; + struct smbcli_tree *tree; + TALLOC_CTX *mem_ctx; int client_num; int fnum; int offset; @@ -53,6 +56,13 @@ struct benchlock_state { union smb_lock io; struct smb_lock_entry lock[2]; struct smbcli_request *req; + struct smb_composite_connect reconnect; + + /* these are used for reconnections */ + int dest_port; + const char *dest_host; + const char *called_name; + const char *service_type; }; static void lock_completion(struct smbcli_request *); @@ -64,11 +74,40 @@ 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].pid = state->tree->session->pid; + state->lock[1].pid = state->tree->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); + state->req = smb_raw_lock_send(state->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; +} + +static void reopen_connection(struct benchlock_state *state); + + +static void reopen_file(struct event_context *ev, struct timed_event *te, + struct timeval t, void *private_data) +{ + struct benchlock_state *state = (struct benchlock_state *)private_data; + + /* reestablish our open file */ + state->fnum = smbcli_open(state->tree, FNAME, O_RDWR|O_CREAT, DENY_NONE); + if (state->fnum == -1) { + printf("Failed to open %s on connection %d\n", FNAME, state->client_num); + exit(1); + } + + /* reestablish one lock, preparing for the async lock loop */ + state->lock[0].offset = state->offset; + state->io.lockx.in.ulock_cnt = 0; + state->io.lockx.in.file.fnum = state->fnum; + state->req = smb_raw_lock_send(state->tree, &state->io); if (state->req == NULL) { DEBUG(0,("Failed to setup lock\n")); lock_failed++; @@ -78,33 +117,70 @@ static void lock_send(struct benchlock_state *state) state->offset = (state->offset+1)%nprocs; } +/* + complete an async reconnect + */ +static void reopen_connection_complete(struct composite_context *ctx) +{ + struct benchlock_state *state = (struct benchlock_state *)ctx->async.private_data; + NTSTATUS status; + struct smb_composite_connect *io = &state->reconnect; + + status = smb_composite_connect_recv(ctx, state->mem_ctx); + if (!NT_STATUS_IS_OK(status)) { + reopen_connection(state); + return; + } + + talloc_free(state->tree); + state->tree = io->out.tree; + + /* do the reopen as a separate event */ + event_add_timed(state->ev, state->mem_ctx, timeval_zero(), reopen_file, state); +} + + + /* reopen dead connections */ static void reopen_connection(struct benchlock_state *state) { - do { - DEBUG(0,("reopening connection %u\n", state->client_num)); - } while (!torture_open_connection_ev(&state->cli, state->client_num, state->ev)); - - state->fnum = smbcli_open(state->cli->tree, FNAME, O_RDWR|O_CREAT, DENY_NONE); - if (state->fnum == -1) { - printf("Failed to open %s on connection %d\n", FNAME, state->client_num); + struct composite_context *ctx; + struct smb_composite_connect *io = &state->reconnect; + char *host, *share; + + if (!torture_get_conn_index(state->client_num, state->mem_ctx, &host, &share)) { + DEBUG(0,("Can't find host/share for reconnect?!\n")); exit(1); } - state->lock[0].offset = state->offset; - state->io.lockx.in.ulock_cnt = 0; - state->req = smb_raw_lock_send(state->cli->tree, &state->io); - if (state->req == NULL) { - DEBUG(0,("Failed to setup lock\n")); - lock_failed++; + io->in.dest_host = state->dest_host; + io->in.port = state->dest_port; + io->in.called_name = state->called_name; + io->in.service = share; + io->in.service_type = state->service_type; + io->in.credentials = cmdline_credentials; + io->in.fallback_to_anonymous = False; + io->in.workgroup = lp_workgroup(); + + DEBUG(0,("reopening connection to //%s/%s\n", host, share)); + + /* kill off the remnants of the old connection */ + talloc_free(state->tree); + state->tree = NULL; + + ctx = smb_composite_connect_send(io, state->mem_ctx, state->ev); + if (ctx == NULL) { + DEBUG(0,("Failed to setup async reconnect\n")); + exit(1); } - state->req->async.private = state; - state->req->async.fn = lock_completion; - state->offset = (state->offset+1)%nprocs; + + ctx->async.fn = reopen_connection_complete; + ctx->async.private_data = state; } + /* called when a lock completes */ @@ -114,10 +190,11 @@ static void lock_completion(struct smbcli_request *req) NTSTATUS status = smbcli_request_simple_recv(req); state->req = NULL; if (!NT_STATUS_IS_OK(status)) { - lock_failed++; - DEBUG(0,("Lock failed - %s\n", nt_errstr(status))); if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) { reopen_connection(state); + } else { + DEBUG(0,("Lock failed - %s\n", nt_errstr(status))); + lock_failed++; } } else { state->count++; @@ -139,6 +216,7 @@ BOOL torture_bench_lock(struct torture_context *torture) struct benchlock_state *state; int total = 0, loops=0, minops=0; NTSTATUS status; + struct smbcli_state *cli; nprocs = lp_parm_int(-1, "torture", "nprocs", 4); @@ -146,20 +224,29 @@ BOOL torture_bench_lock(struct torture_context *torture) printf("Opening %d connections\n", nprocs); for (i=0;itree; + state[i].dest_host = talloc_strdup(state[i].mem_ctx, + cli->tree->session->transport->socket->hostname); + state[i].dest_port = cli->tree->session->transport->socket->port; + state[i].called_name = talloc_strdup(state[i].mem_ctx, + cli->tree->session->transport->called.name); + state[i].service_type = talloc_strdup(state[i].mem_ctx, + cli->tree->device); } - if (!torture_setup_dir(state[0].cli, BASEDIR)) { + if (!torture_setup_dir(cli, BASEDIR)) { goto failed; } for (i=0;itree, + state[i].fnum = smbcli_open(state[i].tree, FNAME, O_RDWR|O_CREAT, DENY_NONE); if (state[i].fnum == -1) { @@ -179,8 +266,8 @@ BOOL torture_bench_lock(struct torture_context *torture) 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); + state[i].lock[0].pid = state[i].tree->session->pid; + status = smb_raw_lock(state[i].tree, &state[i].io); CHECK_STATUS(status, NT_STATUS_OK); } @@ -226,19 +313,14 @@ BOOL torture_bench_lock(struct torture_context *torture) for (i=0;isession); + smb_raw_exit(state[i].tree->session); } - smbcli_deltree(state[0].cli->tree, BASEDIR); + smbcli_deltree(state[0].tree, BASEDIR); talloc_free(mem_ctx); return ret; failed: - for (i=0;isession); - } - smbcli_deltree(state[0].cli->tree, BASEDIR); talloc_free(mem_ctx); return False; }