/* 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 benchopen_state *state; int total = 0; int total_retries = 0; int minops = 0; bool progress=false; progress = torture_setting_bool(torture, "progress", true); nprocs = torture_setting_int(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++) { state[i].tctx = torture; state[i].mem_ctx = talloc_new(state); state[i].client_num = i; state[i].ev = torture->ev; if (!torture_open_connection_ev(&state[i].cli, i, torture, torture->ev)) { return false; } talloc_steal(mem_ctx, state); state[i].tree = state[i].cli->tree; state[i].dest_host = talloc_strdup(state[i].mem_ctx, state[i].cli->tree->session->transport->socket->hostname); state[i].dest_ports = talloc_array(state[i].mem_ctx, const char *, 2); state[i].dest_ports[0] = talloc_asprintf(state[i].dest_ports, "%u", state[i].cli->tree->session->transport->socket->port); state[i].dest_ports[1] = NULL; state[i].called_name = talloc_strdup(state[i].mem_ctx, state[i].cli->tree->session->transport->called.name); state[i].service_type = talloc_strdup(state[i].mem_ctx, state[i].cli->tree->device); } num_connected = i; if (!torture_setup_dir(state[0].cli, BASEDIR)) { goto failed; } fnames = talloc_array(mem_ctx, char *, 3*nprocs); for (i=0;i<3*nprocs;i++) { fnames[i] = talloc_asprintf(fnames, "%s\\file%d.dat", BASEDIR, i); } for (i=0;i<nprocs;i++) { /* all connections start with the same file */ state[i].next_file_num = 0; state[i].open_fnum = -1; state[i].close_fnum = -1; next_open(&state[i]); } tv = timeval_current(); if (progress) { report_te = event_add_timed(torture->ev, state, timeval_current_ofs(1, 0), report_rate, state); } printf("Running for %d seconds\n", timelimit); while (timeval_elapsed(&tv) < timelimit) { event_loop_once(torture->ev); if (open_failed) { DEBUG(0,("open failed\n")); goto failed; } if (close_failed) { DEBUG(0,("open failed\n")); goto failed; } } talloc_free(report_te); if (progress) { for (i=0;i<nprocs;i++) { printf(" "); } printf("\r"); } minops = state[0].count; for (i=0;i<nprocs;i++) { total += state[i].count; total_retries += state[i].open_retries; printf("[%d] %u ops (%u retries)\n", i, state[i].count, state[i].open_retries); if (state[i].count < minops) minops = state[i].count; } printf("%.2f ops/second (%d retries)\n", total/timeval_elapsed(&tv), total_retries); 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].tree->session); } smbcli_deltree(state[0].tree, BASEDIR); talloc_free(mem_ctx); return ret; failed: talloc_free(mem_ctx); return false; }
/* 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 offline_state *state; struct smbcli_state *cli; bool progress; progress = torture_setting_bool(torture, "progress", true); nconnections = torture_setting_int(torture, "nprocs", 4); numstates = nconnections * torture_entries; state = talloc_zero_array(mem_ctx, struct offline_state, numstates); printf("Opening %d connections with %d simultaneous operations and %u files\n", nconnections, numstates, torture_numops); for (i=0;i<nconnections;i++) { state[i].tctx = torture; state[i].mem_ctx = talloc_new(state); state[i].ev = torture->ev; if (!torture_open_connection_ev(&cli, i, torture, torture->ev)) { return false; } state[i].tree = cli->tree; 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 */ for (i=nconnections;i<numstates;i++) { state[i].tctx = torture; state[i].mem_ctx = talloc_new(state); state[i].ev = torture->ev; state[i].tree = state[i % nconnections].tree; state[i].client = i; } num_connected = i; if (!torture_setup_dir(cli, BASEDIR)) { goto failed; } /* pre-create files */ printf("Pre-creating %u files ....\n", torture_numops); for (i=0;i<torture_numops;i++) { int fnum; char *fname = filename(mem_ctx, i); char buf[FILE_SIZE]; NTSTATUS status; memset(buf, 1+(i % 255), sizeof(buf)); fnum = smbcli_open(state[0].tree, fname, O_RDWR|O_CREAT, DENY_NONE); if (fnum == -1) { printf("Failed to open %s on connection %d\n", fname, i); goto failed; } if (smbcli_write(state[0].tree, fnum, 0, buf, 0, sizeof(buf)) != sizeof(buf)) { printf("Failed to write file of size %u\n", FILE_SIZE); goto failed; } status = smbcli_close(state[0].tree, fnum); if (!NT_STATUS_IS_OK(status)) { printf("Close failed - %s\n", nt_errstr(status)); goto failed; } talloc_free(fname); } /* start the async ops */ for (i=0;i<numstates;i++) { state[i].tv_start = timeval_current(); test_offline(&state[i]); } tv = timeval_current(); if (progress) { event_add_timed(torture->ev, state, timeval_current_ofs(1, 0), report_rate, state); } printf("Running for %d seconds\n", timelimit); while (timeval_elapsed(&tv) < timelimit) { event_loop_once(torture->ev); if (test_failed) { DEBUG(0,("test failed\n")); goto failed; } } printf("\nWaiting for completion\n"); test_finished = true; for (i=0;i<numstates;i++) { while (state[i].loadfile || state[i].savefile || state[i].req) { event_loop_once(torture->ev); } } printf("worst latencies: set_lat=%.1f get_lat=%.1f save_lat=%.1f load_lat=%.1f\n", worst_latencies[OP_SETOFFLINE], worst_latencies[OP_GETOFFLINE], worst_latencies[OP_SAVEFILE], worst_latencies[OP_LOADFILE]); smbcli_deltree(state[0].tree, BASEDIR); talloc_free(mem_ctx); printf("\n"); return ret; failed: talloc_free(mem_ctx); return false; }
/* benchmark locking calls */ bool torture_bench_lock(struct torture_context *torture) { bool ret = true; TALLOC_CTX *mem_ctx = talloc_new(torture); int i, j; int timelimit = torture_setting_int(torture, "timelimit", 10); struct timeval tv; struct benchlock_state *state; int total = 0, minops=0; struct smbcli_state *cli; bool progress; off_t offset; int initial_locks = torture_setting_int(torture, "initial_locks", 0); progress = torture_setting_bool(torture, "progress", true); nprocs = torture_setting_int(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++) { state[i].tctx = torture; state[i].mem_ctx = talloc_new(state); state[i].client_num = i; state[i].ev = torture->ev; if (!torture_open_connection_ev(&cli, i, torture, torture->ev)) { return false; } talloc_steal(mem_ctx, state); state[i].tree = cli->tree; state[i].dest_host = talloc_strdup(state[i].mem_ctx, cli->tree->session->transport->socket->hostname); state[i].dest_ports = talloc_array(state[i].mem_ctx, const char *, 2); state[i].dest_ports[0] = talloc_asprintf(state[i].dest_ports, "%u", cli->tree->session->transport->socket->port); state[i].dest_ports[1] = NULL; 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); } num_connected = i; if (!torture_setup_dir(cli, BASEDIR)) { goto failed; } for (i=0;i<nprocs;i++) { state[i].fnum = smbcli_open(state[i].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; } /* Optionally, lock initial_locks for each proc beforehand. */ if (i == 0 && initial_locks > 0) { printf("Initializing %d locks on each proc.\n", initial_locks); } for (j = 0; j < initial_locks; j++) { offset = (0xFFFFFED8LLU * (i+2)) + j; if (!NT_STATUS_IS_OK(smbcli_lock64(state[i].tree, state[i].fnum, offset, 1, 0, WRITE_LOCK))) { printf("Failed initializing, lock=%d\n", j); goto failed; } } state[i].stage = LOCK_INITIAL; lock_send(&state[i]); } tv = timeval_current(); if (progress) { event_add_timed(torture->ev, state, timeval_current_ofs(1, 0), report_rate, state); } printf("Running for %d seconds\n", timelimit); while (timeval_elapsed(&tv) < timelimit) { event_loop_once(torture->ev); if (lock_failed) { DEBUG(0,("locking failed\n")); goto failed; } } printf("%.2f ops/second\n", total/timeval_elapsed(&tv)); 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 locking\n"); goto failed; } for (i=0;i<nprocs;i++) { talloc_free(state[i].req); smb_raw_exit(state[i].tree->session); } smbcli_deltree(state[0].tree, BASEDIR); talloc_free(mem_ctx); printf("\n"); return ret; failed: smbcli_deltree(state[0].tree, BASEDIR); talloc_free(mem_ctx); return false; }