#include "libcli/composite/composite.h"
extern struct cli_credentials *cmdline_credentials;
-static void benchrw_callback(struct smbcli_request *req);
-enum benchrw_stage {
- START,
- OPEN_CONNECTION,
- CLEANUP_TESTDIR,
- MK_TESTDIR,
- OPEN_FILE,
- INITIAL_WRITE,
- READ_WRITE_DATA,
- MAX_OPS_REACHED,
- ERROR,
- CLOSE_FILE,
- CLEANUP,
- FINISHED
-};
-
-struct benchrw_state{
- struct torture_context *tctx;
- char *dname;
- char *fname;
- uint16_t fnum;
- int nr;
- struct smbcli_tree *cli;
- uint8_t *buffer;
- int writecnt;
- int readcnt;
- int completed;
- void *req_params;
- enum benchrw_stage mode;
- struct params{
- struct unclist{
- const char *host;
- const char *share;
- } **unc;
- const char *workgroup;
- int retry;
- unsigned int writeblocks;
- unsigned int blocksize;
- unsigned int writeratio;
- } *lp_params;
- };
static BOOL wait_lock(struct smbcli_state *c, int fnum, uint32_t offset, uint32_t len)
{
return False;
}
+ generate_random_buffer(buf, sizeof(buf));
for (i=0;i<torture_numops;i++) {
uint_t n = (uint_t)random()%10;
return True;
}
+static void benchrw_callback(struct smbcli_request *req);
+enum benchrw_stage {
+ START,
+ OPEN_CONNECTION,
+ CLEANUP_TESTDIR,
+ MK_TESTDIR,
+ OPEN_FILE,
+ INITIAL_WRITE,
+ READ_WRITE_DATA,
+ MAX_OPS_REACHED,
+ ERROR,
+ CLOSE_FILE,
+ CLEANUP,
+ FINISHED
+};
+
+struct benchrw_state {
+ struct torture_context *tctx;
+ char *dname;
+ char *fname;
+ uint16_t fnum;
+ int nr;
+ struct smbcli_tree *cli;
+ uint8_t *buffer;
+ int writecnt;
+ int readcnt;
+ int completed;
+ int num_parallel_requests;
+ void *req_params;
+ enum benchrw_stage mode;
+ struct params{
+ struct unclist{
+ const char *host;
+ const char *share;
+ } **unc;
+ const char *workgroup;
+ int retry;
+ unsigned int writeblocks;
+ unsigned int blocksize;
+ unsigned int writeratio;
+ int num_parallel_requests;
+ } *lp_params;
+};
+
/*
init params using lp_parm_xxx
return number of unclist entries
*/
-static int init_benchrw_params(struct torture_context *tctx, struct params *lpar)
+static int init_benchrw_params(struct torture_context *tctx,
+ struct params *lpar)
{
char **unc_list = NULL;
int num_unc_names = 0, conn_index=0, empty_lines=0;
lpar->blocksize = torture_setting_int(tctx, "blocksize",65535);
lpar->writeblocks = torture_setting_int(tctx, "writeblocks",15);
lpar->writeratio = torture_setting_int(tctx, "writeratio",5);
+ lpar->num_parallel_requests = torture_setting_int(
+ tctx, "parallel_requests", 5);
lpar->workgroup = lp_workgroup();
p = torture_setting_string(tctx, "unclist", NULL);
char *h, *s;
unc_list = file_lines_load(p, &num_unc_names, NULL);
if (!unc_list || num_unc_names <= 0) {
- torture_comment(tctx, "Failed to load unc names list from '%s'\n", p);
+ torture_comment(tctx, "Failed to load unc names list "
+ "from '%s'\n", p);
exit(1);
}
- lpar->unc = talloc_array(tctx, struct unclist *, (num_unc_names-empty_lines));
+ lpar->unc = talloc_array(tctx, struct unclist *,
+ (num_unc_names-empty_lines));
for(conn_index = 0; conn_index < num_unc_names; conn_index++) {
/* ignore empty lines */
if(strlen(unc_list[conn_index % num_unc_names])==0){
empty_lines++;
continue;
}
- if (!smbcli_parse_unc(unc_list[conn_index % num_unc_names],
- NULL, &h, &s)) {
- torture_comment(tctx, "Failed to parse UNC name %s\n",
- unc_list[conn_index % num_unc_names]);
+ if (!smbcli_parse_unc(
+ unc_list[conn_index % num_unc_names],
+ NULL, &h, &s)) {
+ torture_comment(
+ tctx, "Failed to parse UNC "
+ "name %s\n",
+ unc_list[conn_index % num_unc_names]);
exit(1);
}
- lpar->unc[conn_index-empty_lines] = talloc(tctx,struct unclist);
- lpar->unc[conn_index-empty_lines]->host = h;
- lpar->unc[conn_index-empty_lines]->share = s;
+ lpar->unc[conn_index-empty_lines] =
+ talloc(tctx, struct unclist);
+ lpar->unc[conn_index-empty_lines]->host = h;
+ lpar->unc[conn_index-empty_lines]->share = s;
}
return num_unc_names-empty_lines;
}else{
lpar->unc = talloc_array(tctx, struct unclist *, 1);
lpar->unc[0] = talloc(tctx,struct unclist);
- lpar->unc[0]->host = torture_setting_string(tctx, "host", NULL);
- lpar->unc[0]->share = torture_setting_string(tctx, "share", NULL);
+ lpar->unc[0]->host = torture_setting_string(tctx, "host",
+ NULL);
+ lpar->unc[0]->share = torture_setting_string(tctx, "share",
+ NULL);
return 1;
}
}
/*
Called when the reads & writes are finished. closes the file.
*/
-static NTSTATUS benchrw_close(struct torture_context *tctx,struct smbcli_request *req,
- struct benchrw_state *state)
+static NTSTATUS benchrw_close(struct torture_context *tctx,
+ struct smbcli_request *req,
+ struct benchrw_state *state)
{
union smb_close close_parms;
return NT_STATUS_OK;
}
+static NTSTATUS benchrw_readwrite(struct torture_context *tctx,
+ struct benchrw_state *state);
+static void benchrw_callback(struct smbcli_request *req);
+
+static void benchrw_rw_callback(struct smbcli_request *req)
+{
+ struct benchrw_state *state = req->async.private;
+ struct torture_context *tctx = state->tctx;
+
+ if (!NT_STATUS_IS_OK(req->status)) {
+ state->mode = ERROR;
+ return;
+ }
+
+ state->completed++;
+ state->num_parallel_requests--;
+
+ if ((state->completed >= torture_numops)
+ && (state->num_parallel_requests == 0)) {
+ benchrw_callback(req);
+ talloc_free(req);
+ return;
+ }
+
+ talloc_free(req);
+
+ if (state->completed + state->num_parallel_requests
+ < torture_numops) {
+ benchrw_readwrite(tctx, state);
+ }
+}
+
/*
Called when the initial write is completed is done. write or read a file.
*/
-static NTSTATUS benchrw_readwrite(struct torture_context *tctx,struct smbcli_request *req,
- struct benchrw_state *state)
+static NTSTATUS benchrw_readwrite(struct torture_context *tctx,
+ struct benchrw_state *state)
{
+ struct smbcli_request *req;
union smb_read rd;
union smb_write wr;
- NT_STATUS_NOT_OK_RETURN(req->status);
- talloc_free(req);
-
- state->completed++;
- /*rotate between writes and reads*/
- if( state->completed % state->lp_params->writeratio == 0){
+ /* randomize between writes and reads*/
+ if ( random() % state->lp_params->writeratio == 0) {
torture_comment(tctx, "Callback WRITE file:%d (%d/%d)\n",
state->nr,state->completed,torture_numops);
wr.generic.level = RAW_WRITE_WRITEX ;
wr.writex.in.data = state->buffer;
state->readcnt=0;
req = smb_raw_write_send(state->cli,&wr);
- }else{
- torture_comment(tctx, "Callback READ file:%d (%d/%d) Offset:%d\n",
+ }
+ else {
+ torture_comment(tctx,
+ "Callback READ file:%d (%d/%d) Offset:%d\n",
state->nr,state->completed,torture_numops,
(state->readcnt*state->lp_params->blocksize));
rd.generic.level = RAW_READ_READ ;
}
req = smb_raw_read_send(state->cli,&rd);
}
+ state->num_parallel_requests += 1;
NT_STATUS_HAVE_NO_MEMORY(req);
/*register the callback function!*/
- req->async.fn = benchrw_callback;
+ req->async.fn = benchrw_rw_callback;
req->async.private = state;
return NT_STATUS_OK;
/*
Called when the open is done. writes to the file.
*/
-static NTSTATUS benchrw_open(struct torture_context *tctx,struct smbcli_request *req,
- struct benchrw_state *state)
+static NTSTATUS benchrw_open(struct torture_context *tctx,
+ struct smbcli_request *req,
+ struct benchrw_state *state)
{
union smb_write wr;
if(state->mode == OPEN_FILE){
/*
Called when the mkdir is done. Opens a file.
*/
-static NTSTATUS benchrw_mkdir(struct torture_context *tctx,struct smbcli_request *req,
- struct benchrw_state *state)
+static NTSTATUS benchrw_mkdir(struct torture_context *tctx,
+ struct smbcli_request *req,
+ struct benchrw_state *state)
{
union smb_open *open_parms;
uint8_t *writedata;
/* open/create the files */
torture_comment(tctx, "Open File %d/%d\n",state->nr+1,
- lp_parm_int(-1, "torture", "nprocs", 4));
+ lp_parm_int(-1, "torture", "nprocs", 4));
open_parms=talloc_zero(tctx, union smb_open);
NT_STATUS_HAVE_NO_MEMORY(open_parms);
open_parms->openx.level = RAW_OPEN_OPENX;
struct torture_context *tctx = state->tctx;
/*dont send new requests when torture_numops is reached*/
- if(state->completed >= torture_numops){
- state->completed=0;
+ if ((state->mode == READ_WRITE_DATA)
+ && (state->completed >= torture_numops)) {
state->mode=MAX_OPS_REACHED;
}
switch (state->mode) {
case MK_TESTDIR:
- if (!NT_STATUS_IS_OK(benchrw_mkdir(tctx, req,state))) {
- torture_comment(tctx, "Failed to create the test directory - %s\n",
- nt_errstr(req->status));
+ if (!NT_STATUS_IS_OK(benchrw_mkdir(tctx, req,state))) {
+ torture_comment(tctx, "Failed to create the test "
+ "directory - %s\n",
+ nt_errstr(req->status));
state->mode=ERROR;
return;
}
case OPEN_FILE:
case INITIAL_WRITE:
if (!NT_STATUS_IS_OK(benchrw_open(tctx, req,state))){
- torture_comment(tctx, "Failed to open/write the file - %s\n",
- nt_errstr(req->status));
+ torture_comment(tctx, "Failed to open/write the "
+ "file - %s\n",
+ nt_errstr(req->status));
state->mode=ERROR;
return;
}
break;
case READ_WRITE_DATA:
- if (!NT_STATUS_IS_OK(benchrw_readwrite(tctx,req,state))){
- torture_comment(tctx, "Failed to read/write the file - %s\n",
- nt_errstr(req->status));
- state->mode=ERROR;
- return;
+ while (state->num_parallel_requests
+ < state->lp_params->num_parallel_requests) {
+ NTSTATUS status;
+ status = benchrw_readwrite(tctx,state);
+ if (!NT_STATUS_IS_OK(status)){
+ torture_comment(tctx, "Failed to read/write "
+ "the file - %s\n",
+ nt_errstr(req->status));
+ state->mode=ERROR;
+ return;
+ }
}
break;
case MAX_OPS_REACHED:
if (!NT_STATUS_IS_OK(benchrw_close(tctx,req,state))){
- torture_comment(tctx, "Failed to read/write/close the file - %s\n",
- nt_errstr(req->status));
+ torture_comment(tctx, "Failed to read/write/close "
+ "the file - %s\n",
+ nt_errstr(req->status));
state->mode=ERROR;
return;
}
case CLOSE_FILE:
torture_comment(tctx, "File %d closed\n",state->nr);
if (!NT_STATUS_IS_OK(req->status)) {
- torture_comment(tctx, "Failed to close the file - %s\n",
- nt_errstr(req->status));
+ torture_comment(tctx, "Failed to close the "
+ "file - %s\n",
+ nt_errstr(req->status));
state->mode=ERROR;
return;
}
state->mode=CLEANUP_TESTDIR;
}else{
if(state->writecnt < retry){
- torture_comment(tctx, "Failed to open connection:%d, Retry (%d/%d)\n",
+ torture_comment(tctx, "Failed to open connection: "
+ "%d, Retry (%d/%d)\n",
state->nr,state->writecnt,retry);
state->writecnt++;
state->mode=START;
usleep(1000);
}else{
- torture_comment(tctx, "Failed to open connection (%d) - %s\n",
+ torture_comment(tctx, "Failed to open connection "
+ "(%d) - %s\n",
state->nr, nt_errstr(con->status));
state->mode=ERROR;
}
BOOL success=True;
int torture_nprocs = lp_parm_int(-1, "torture", "nprocs", 4);
- torture_comment(tctx, "Start BENCH-READWRITE num_ops=%d num_nprocs=%d\n",
- torture_numops, torture_nprocs);
+ torture_comment(tctx, "Start BENCH-READWRITE num_ops=%d "
+ "num_nprocs=%d\n",
+ torture_numops, torture_nprocs);
/*init talloc context*/
ev = event_context_init(tctx);
state[i]=talloc(tctx,struct benchrw_state);
state[i]->tctx = tctx;
state[i]->completed=0;
+ state[i]->num_parallel_requests=0;
state[i]->lp_params=&lpparams;
state[i]->nr=i;
state[i]->dname=talloc_asprintf(tctx,"benchrw%d",i);
state[i]->fname=talloc_asprintf(tctx,"%s%s",
- state[i]->dname,fname);
+ state[i]->dname,fname);
state[i]->mode=START;
state[i]->writecnt=0;
}
switch (state[i]->mode){
/*open multiple connections with the same userid */
case START:
- smb_con = talloc(tctx,struct smb_composite_connect) ;
+ smb_con = talloc(
+ tctx,struct smb_composite_connect) ;
state[i]->req_params=smb_con;
state[i]->mode=OPEN_CONNECTION;
- req1 = torture_connect_async(tctx, smb_con,
- tctx,ev,
- lpparams.unc[i % num_unc_names]->host,
- lpparams.unc[i % num_unc_names]->share,
- lpparams.workgroup);
+ req1 = torture_connect_async(
+ tctx, smb_con, tctx,ev,
+ lpparams.unc[i % num_unc_names]->host,
+ lpparams.unc[i % num_unc_names]->share,
+ lpparams.workgroup);
/* register callback fn + private data */
req1->async.fn = async_open_callback;
req1->async.private_data=state[i];
smb_raw_exit(state[i]->cli->session);
if (smbcli_deltree(state[i]->cli,
state[i]->dname) == -1) {
- torture_comment(tctx, "Unable to delete %s - %s\n",
+ torture_comment(
+ tctx,
+ "Unable to delete %s - %s\n",
state[i]->dname,
smbcli_errstr(state[i]->cli));
state[i]->mode=ERROR;
break;
/* cleanup , close connection */
case CLEANUP:
- torture_comment(tctx, "Deleting test dir %s %d/%d\n",state[i]->dname,
+ torture_comment(tctx, "Deleting test dir %s "
+ "%d/%d\n",state[i]->dname,
i+1,torture_nprocs);
smbcli_deltree(state[i]->cli,state[i]->dname);
if (NT_STATUS_IS_ERR(smb_tree_disconnect(
- state[i]->cli))) {
- torture_comment(tctx, "ERROR: Tree disconnect failed");
+ state[i]->cli))) {
+ torture_comment(tctx, "ERROR: Tree "
+ "disconnect failed");
state[i]->mode=ERROR;
break;
}