From 4e4e7dbff8f248024ed9150ef2387a186cac61a6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 25 Jan 2008 15:00:11 +1100 Subject: added a offline file torture test BASE-OFFLINE (This used to be commit d4b26fb2a38aa5b0ed2b6083641b9d8306af8c58) --- source4/torture/raw/offline.c | 455 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 455 insertions(+) create mode 100644 source4/torture/raw/offline.c (limited to 'source4/torture/raw/offline.c') diff --git a/source4/torture/raw/offline.c b/source4/torture/raw/offline.c new file mode 100644 index 0000000000..234b962147 --- /dev/null +++ b/source4/torture/raw/offline.c @@ -0,0 +1,455 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2008 + + 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 3 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, see . +*/ + +/* + test offline files + */ + +#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" +#include "libcli/composite/composite.h" +#include "libcli/smb_composite/smb_composite.h" +#include "libcli/resolve/resolve.h" +#include "param/param.h" + +#define BASEDIR "\\testoffline" + +static int nconnections; +static int numstates; +static int num_connected; +static int test_failed; +extern int torture_numops; +static bool test_finished; + +#define FILE_SIZE 8192 + +enum offline_op {OP_LOADFILE, OP_SAVEFILE, OP_SETOFFLINE, OP_GETOFFLINE, OP_ENDOFLIST}; + +struct offline_state { + struct torture_context *tctx; + struct event_context *ev; + struct smbcli_tree *tree; + TALLOC_CTX *mem_ctx; + int fnum; + uint32_t count; + uint32_t lastcount; + uint32_t fnumber; + char *fname; + struct smb_composite_loadfile *loadfile; + struct smb_composite_savefile *savefile; + struct smbcli_request *req; + enum offline_op op; +}; + +static void test_offline(struct offline_state *state); + + +static char *filename(TALLOC_CTX *ctx, int i) +{ + char *s = talloc_asprintf(ctx, BASEDIR "\\file%u.dat", i); + return s; +} + + +/* + called when a loadfile completes + */ +static void loadfile_callback(struct composite_context *ctx) +{ + struct offline_state *state = ctx->async.private_data; + NTSTATUS status; + int i; + + status = smb_composite_loadfile_recv(ctx, state->mem_ctx); + if (!NT_STATUS_IS_OK(status)) { + printf("Failed to read file '%s' - %s\n", + state->loadfile->in.fname, nt_errstr(status)); + test_failed++; + } + + /* check the data is correct */ + if (state->loadfile->out.size != FILE_SIZE) { + printf("Wrong file size %u - expected %u\n", + state->loadfile->out.size, FILE_SIZE); + test_failed++; + return; + } + + for (i=0;iloadfile->out.data[i] != state->fnumber % 256) { + printf("Bad data in file %u\n", state->fnumber); + test_failed++; + return; + } + } + + talloc_steal(state->loadfile, state->loadfile->out.data); + + state->count++; + talloc_free(state->loadfile); + state->loadfile = NULL; + + if (!test_finished) { + test_offline(state); + } +} + + +/* + called when a savefile completes + */ +static void savefile_callback(struct composite_context *ctx) +{ + struct offline_state *state = ctx->async.private_data; + NTSTATUS status; + + status = smb_composite_savefile_recv(ctx); + if (!NT_STATUS_IS_OK(status)) { + printf("Failed to save file '%s' - %s\n", + state->savefile->in.fname, nt_errstr(status)); + test_failed++; + } + + state->count++; + talloc_free(state->savefile); + state->savefile = NULL; + + if (!test_finished) { + test_offline(state); + } +} + + +/* + called when a setoffline completes + */ +static void setoffline_callback(struct smbcli_request *req) +{ + struct offline_state *state = req->async.private; + NTSTATUS status; + + status = smbcli_request_simple_recv(req); + if (!NT_STATUS_IS_OK(status)) { + printf("Failed to set offline file '%s' - %s\n", + state->fname, nt_errstr(status)); + test_failed++; + } + + state->req = NULL; + state->count++; + + if (!test_finished) { + test_offline(state); + } +} + + +/* + called when a getoffline completes + */ +static void getoffline_callback(struct smbcli_request *req) +{ + struct offline_state *state = req->async.private; + NTSTATUS status; + union smb_fileinfo io; + + io.standard.level = RAW_FILEINFO_GETATTR; + + status = smb_raw_pathinfo_recv(req, state->mem_ctx, &io); + if (!NT_STATUS_IS_OK(status)) { + printf("Failed to get offline file '%s' - %s\n", + state->fname, nt_errstr(status)); + test_failed++; + } + + state->req = NULL; + state->count++; + + if (!test_finished) { + test_offline(state); + } +} + + +/* + send the next offline file fetch request +*/ +static void test_offline(struct offline_state *state) +{ + struct composite_context *ctx; + + state->op = (enum offline_op) (random() % OP_ENDOFLIST); + + state->fnumber = random() % torture_numops; + talloc_free(state->fname); + state->fname = filename(state->mem_ctx, state->fnumber); + + switch (state->op) { + case OP_LOADFILE: + state->loadfile = talloc_zero(state->mem_ctx, struct smb_composite_loadfile); + state->loadfile->in.fname = state->fname; + + ctx = smb_composite_loadfile_send(state->tree, state->loadfile); + if (ctx == NULL) { + printf("Failed to setup loadfile for %s\n", state->fname); + test_failed = true; + } + + talloc_steal(state->loadfile, ctx); + + ctx->async.fn = loadfile_callback; + ctx->async.private_data = state; + break; + + case OP_SAVEFILE: + state->savefile = talloc_zero(state->mem_ctx, struct smb_composite_savefile); + + state->savefile->in.fname = state->fname; + state->savefile->in.data = talloc_size(state->savefile, FILE_SIZE); + state->savefile->in.size = FILE_SIZE; + memset(state->savefile->in.data, state->fnumber, FILE_SIZE); + + ctx = smb_composite_savefile_send(state->tree, state->savefile); + if (ctx == NULL) { + printf("Failed to setup savefile for %s\n", state->fname); + test_failed = true; + } + + talloc_steal(state->savefile, ctx); + + ctx->async.fn = savefile_callback; + ctx->async.private_data = state; + break; + + case OP_SETOFFLINE: { + union smb_setfileinfo io; + ZERO_STRUCT(io); + io.setattr.level = RAW_SFILEINFO_SETATTR; + io.setattr.in.attrib = FILE_ATTRIBUTE_OFFLINE; + io.setattr.in.file.path = state->fname; + + state->req = smb_raw_setpathinfo_send(state->tree, &io); + if (state->req == NULL) { + printf("Failed to setup setoffline for %s\n", state->fname); + test_failed = true; + } + + state->req->async.fn = setoffline_callback; + state->req->async.private = state; + break; + } + + case OP_GETOFFLINE: { + union smb_fileinfo io; + ZERO_STRUCT(io); + io.standard.level = RAW_FILEINFO_GETATTR; + io.standard.in.file.path = state->fname; + + state->req = smb_raw_pathinfo_send(state->tree, &io); + if (state->req == NULL) { + printf("Failed to setup getoffline for %s\n", state->fname); + test_failed = true; + } + + state->req->async.fn = getoffline_callback; + state->req->async.private = state; + break; + } + + default: + printf("bad operation??\n"); + break; + } +} + + + + +static void echo_completion(struct smbcli_request *req) +{ + struct offline_state *state = (struct offline_state *)req->async.private; + NTSTATUS status = smbcli_request_simple_recv(req); + if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE) || + NT_STATUS_EQUAL(status, NT_STATUS_LOCAL_DISCONNECT)) { + talloc_free(state->tree); + state->tree = NULL; + num_connected--; + DEBUG(0,("lost connection\n")); + test_failed++; + } +} + +static void report_rate(struct event_context *ev, struct timed_event *te, + struct timeval t, void *private_data) +{ + struct offline_state *state = talloc_get_type(private_data, + struct offline_state); + int i; + for (i=0;isession->transport, &p); + req->async.private = &state[i]; + req->async.fn = echo_completion; + } +} + +/* + test offline file handling +*/ +bool torture_test_offline(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 offline_state *state; + int total = 0; + struct smbcli_state *cli; + bool progress; + progress = torture_setting_bool(torture, "progress", true); + + nconnections = torture_setting_int(torture, "nconnections", 4); + numstates = nconnections * 5; + + state = talloc_zero_array(mem_ctx, struct offline_state, numstates); + + printf("Opening %d connections with %d simultaneous operations\n", nconnections, numstates); + for (i=0;itree; + } + + /* the others are repeats on the earlier connections */ + for (i=nconnections;i Date: Fri, 25 Jan 2008 15:00:45 +1100 Subject: more useful output (This used to be commit 033cab6546d943089eefc298b335db03c1d0ebb6) --- source4/torture/raw/offline.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'source4/torture/raw/offline.c') diff --git a/source4/torture/raw/offline.c b/source4/torture/raw/offline.c index 234b962147..4b7d108b0f 100644 --- a/source4/torture/raw/offline.c +++ b/source4/torture/raw/offline.c @@ -57,6 +57,8 @@ struct offline_state { uint32_t count; uint32_t lastcount; uint32_t fnumber; + uint32_t offline_count; + uint32_t online_count; char *fname; struct smb_composite_loadfile *loadfile; struct smb_composite_savefile *savefile; @@ -176,7 +178,7 @@ static void getoffline_callback(struct smbcli_request *req) NTSTATUS status; union smb_fileinfo io; - io.standard.level = RAW_FILEINFO_GETATTR; + io.getattr.level = RAW_FILEINFO_GETATTR; status = smb_raw_pathinfo_recv(req, state->mem_ctx, &io); if (!NT_STATUS_IS_OK(status)) { @@ -185,6 +187,12 @@ static void getoffline_callback(struct smbcli_request *req) test_failed++; } + if (io.getattr.out.attrib & FILE_ATTRIBUTE_OFFLINE) { + state->offline_count++; + } else { + state->online_count++; + } + state->req = NULL; state->count++; @@ -265,8 +273,8 @@ static void test_offline(struct offline_state *state) case OP_GETOFFLINE: { union smb_fileinfo io; ZERO_STRUCT(io); - io.standard.level = RAW_FILEINFO_GETATTR; - io.standard.in.file.path = state->fname; + io.getattr.level = RAW_FILEINFO_GETATTR; + io.getattr.in.file.path = state->fname; state->req = smb_raw_pathinfo_send(state->tree, &io); if (state->req == NULL) { @@ -308,11 +316,13 @@ static void report_rate(struct event_context *ev, struct timed_event *te, struct offline_state *state = talloc_get_type(private_data, struct offline_state); int i; + uint32_t total=0; for (i=0;ioffline_count, state->online_count); fflush(stdout); event_add_timed(ev, state, timeval_current_ofs(1, 0), report_rate, state); @@ -347,7 +357,6 @@ bool torture_test_offline(struct torture_context *torture) struct timeval tv; struct event_context *ev = event_context_find(mem_ctx); struct offline_state *state; - int total = 0; struct smbcli_state *cli; bool progress; progress = torture_setting_bool(torture, "progress", true); @@ -432,9 +441,7 @@ bool torture_test_offline(struct torture_context *torture) } } - printf("%.2f ops/second\n", total/timeval_elapsed(&tv)); - - printf("Waiting for completion\n"); + printf("\nWaiting for completion\n"); test_finished = true; for (i=0;i Date: Fri, 25 Jan 2008 17:27:36 +1100 Subject: added latency reporting (This used to be commit f0ffbb8e19c1085bf54d226f62c667868e14f62e) --- source4/torture/raw/offline.c | 57 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-) (limited to 'source4/torture/raw/offline.c') diff --git a/source4/torture/raw/offline.c b/source4/torture/raw/offline.c index 4b7d108b0f..754185ec62 100644 --- a/source4/torture/raw/offline.c +++ b/source4/torture/raw/offline.c @@ -44,15 +44,20 @@ static int test_failed; extern int torture_numops; static bool test_finished; +enum offline_op {OP_LOADFILE, OP_SAVEFILE, OP_SETOFFLINE, OP_GETOFFLINE, OP_ENDOFLIST}; + +static double latencies[OP_ENDOFLIST]; +static double worst_latencies[OP_ENDOFLIST]; + #define FILE_SIZE 8192 -enum offline_op {OP_LOADFILE, OP_SAVEFILE, OP_SETOFFLINE, OP_GETOFFLINE, OP_ENDOFLIST}; struct offline_state { struct torture_context *tctx; struct event_context *ev; struct smbcli_tree *tree; TALLOC_CTX *mem_ctx; + int client; int fnum; uint32_t count; uint32_t lastcount; @@ -64,6 +69,7 @@ struct offline_state { struct smb_composite_savefile *savefile; struct smbcli_request *req; enum offline_op op; + struct timeval tv_start; }; static void test_offline(struct offline_state *state); @@ -208,6 +214,12 @@ static void getoffline_callback(struct smbcli_request *req) static void test_offline(struct offline_state *state) { struct composite_context *ctx; + double lat; + + lat = timeval_elapsed(&state->tv_start); + if (latencies[state->op] < lat) { + latencies[state->op] = lat; + } state->op = (enum offline_op) (random() % OP_ENDOFLIST); @@ -215,6 +227,8 @@ static void test_offline(struct offline_state *state) talloc_free(state->fname); state->fname = filename(state->mem_ctx, state->fnumber); + state->tv_start = timeval_current(); + switch (state->op) { case OP_LOADFILE: state->loadfile = talloc_zero(state->mem_ctx, struct smb_composite_loadfile); @@ -258,6 +272,9 @@ static void test_offline(struct offline_state *state) io.setattr.level = RAW_SFILEINFO_SETATTR; io.setattr.in.attrib = FILE_ATTRIBUTE_OFFLINE; io.setattr.in.file.path = state->fname; + /* make the file 1 hour old, to get past mininum age restrictions + for HSM systems */ + io.setattr.in.write_time = time(NULL) - 60*60; state->req = smb_raw_setpathinfo_send(state->tree, &io); if (state->req == NULL) { @@ -316,16 +333,32 @@ static void report_rate(struct event_context *ev, struct timed_event *te, struct offline_state *state = talloc_get_type(private_data, struct offline_state); int i; - uint32_t total=0; + uint32_t total=0, total_offline=0, total_online=0; for (i=0;i latencies[state[i].op]) { + latencies[state[i].op] = timeval_elapsed(&state[i].tv_start); + } state[i].lastcount = state[i].count; + total_online += state[i].online_count; + total_offline += state[i].offline_count; } - printf("ops=%6u offline_count=%6u online_count=%6u\r", - total, state->offline_count, state->online_count); + printf("ops/s=%4u offline=%5u online=%4u set_lat=%.1f get_lat=%.1f save_lat=%.1f load_lat=%.1f\r", + total, total_offline, total_online, + latencies[OP_SETOFFLINE], + latencies[OP_GETOFFLINE], + latencies[OP_SAVEFILE], + latencies[OP_LOADFILE]); fflush(stdout); event_add_timed(ev, state, timeval_current_ofs(1, 0), report_rate, state); + for (i=0;i worst_latencies[i]) { + worst_latencies[i] = latencies[i]; + } + latencies[i] = 0; + } + /* send an echo on each interface to ensure it stays alive - this helps with IP takeover */ for (i=0;itree; + state[i].client = i; + /* allow more time for offline files */ + state[i].tree->session->transport->options.request_timeout = 200; } /* the others are repeats on the earlier connections */ @@ -383,6 +419,7 @@ bool torture_test_offline(struct torture_context *torture) state[i].mem_ctx = talloc_new(state); state[i].ev = ev; state[i].tree = state[i % nconnections].tree; + state[i].client = i; } num_connected = i; @@ -392,6 +429,7 @@ bool torture_test_offline(struct torture_context *torture) } /* pre-create files */ + printf("Pre-creating %u files ....\n", torture_numops); for (i=0;i Date: Thu, 7 Feb 2008 23:05:44 +1100 Subject: make the multiplier in the RAW-OFFLINE test settable (This used to be commit f4b363d7a65023c816264b58d6f3f07730b43c0c) --- source4/torture/raw/offline.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/torture/raw/offline.c') diff --git a/source4/torture/raw/offline.c b/source4/torture/raw/offline.c index 754185ec62..1340692faa 100644 --- a/source4/torture/raw/offline.c +++ b/source4/torture/raw/offline.c @@ -42,6 +42,7 @@ static int numstates; static int num_connected; static int test_failed; extern int torture_numops; +extern int torture_entries; static bool test_finished; enum offline_op {OP_LOADFILE, OP_SAVEFILE, OP_SETOFFLINE, OP_GETOFFLINE, OP_ENDOFLIST}; @@ -395,7 +396,7 @@ bool torture_test_offline(struct torture_context *torture) progress = torture_setting_bool(torture, "progress", true); nconnections = torture_setting_int(torture, "nprocs", 4); - numstates = nconnections * 5; + numstates = nconnections * torture_entries; state = talloc_zero_array(mem_ctx, struct offline_state, numstates); -- cgit