/* test readx ops */ static BOOL test_readx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx) { union smb_read io; NTSTATUS status; BOOL ret = True; int fnum; uint8_t *buf; const int maxsize = 90000; const char *fname = BASEDIR "\\test.txt"; const char *test_data = "TEST DATA"; uint_t seed = time(NULL); buf = talloc_zero_size(mem_ctx, maxsize); if (!torture_setup_dir(cli, BASEDIR)) { return False; } printf("Testing RAW_READ_READX\n"); fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE); if (fnum == -1) { printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)); ret = False; goto done; } printf("Trying empty file read\n"); io.generic.level = RAW_READ_READX; io.readx.in.file.fnum = fnum; io.readx.in.mincnt = 1; io.readx.in.maxcnt = 1; io.readx.in.offset = 0; io.readx.in.remaining = 0; io.readx.in.read_for_execute = False; io.readx.out.data = buf; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, 0); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); printf("Trying zero file read\n"); io.readx.in.mincnt = 0; io.readx.in.maxcnt = 0; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, 0); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); printf("Trying bad fnum\n"); io.readx.in.file.fnum = fnum+1; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE); io.readx.in.file.fnum = fnum; smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data)); printf("Trying small read\n"); io.readx.in.file.fnum = fnum; io.readx.in.offset = 0; io.readx.in.remaining = 0; io.readx.in.read_for_execute = False; io.readx.in.mincnt = strlen(test_data); io.readx.in.maxcnt = strlen(test_data); status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, strlen(test_data)); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); if (memcmp(buf, test_data, strlen(test_data)) != 0) { ret = False; printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf); goto done; } printf("Trying short read\n"); io.readx.in.offset = 1; io.readx.in.mincnt = strlen(test_data); io.readx.in.maxcnt = strlen(test_data); status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, strlen(test_data)-1); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) { ret = False; printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf); goto done; } if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) { printf("Trying max offset\n"); io.readx.in.offset = 0xffffffff; io.readx.in.mincnt = strlen(test_data); io.readx.in.maxcnt = strlen(test_data); status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, 0); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); } setup_buffer(buf, seed, maxsize); smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize); memset(buf, 0, maxsize); printf("Trying large read\n"); io.readx.in.offset = 0; io.readx.in.mincnt = 0xFFFF; io.readx.in.maxcnt = 0xFFFF; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt); CHECK_BUFFER(buf, seed, io.readx.out.nread); printf("Trying extra large read\n"); io.readx.in.offset = 0; io.readx.in.mincnt = 100; io.readx.in.maxcnt = 80000; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); if (lp_parm_bool(-1, "torture", "samba3", False)) { printf("SAMBA3: large read extension\n"); CHECK_VALUE(io.readx.out.nread, 80000); } else { CHECK_VALUE(io.readx.out.nread, 0); } CHECK_BUFFER(buf, seed, io.readx.out.nread); printf("Trying mincnt > maxcnt\n"); memset(buf, 0, maxsize); io.readx.in.offset = 0; io.readx.in.mincnt = 30000; io.readx.in.maxcnt = 20000; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt); CHECK_BUFFER(buf, seed, io.readx.out.nread); printf("Trying mincnt < maxcnt\n"); memset(buf, 0, maxsize); io.readx.in.offset = 0; io.readx.in.mincnt = 20000; io.readx.in.maxcnt = 30000; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.remaining, 0xFFFF); CHECK_VALUE(io.readx.out.compaction_mode, 0); CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt); CHECK_BUFFER(buf, seed, io.readx.out.nread); if (cli->transport->negotiate.capabilities & CAP_LARGE_READX) { printf("Trying large readx\n"); io.readx.in.offset = 0; io.readx.in.mincnt = 0; io.readx.in.maxcnt = 0x10000 - 1; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, 0xFFFF); io.readx.in.maxcnt = 0x10000; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); if (lp_parm_bool(-1, "torture", "samba3", False)) { printf("SAMBA3: large read extension\n"); CHECK_VALUE(io.readx.out.nread, 0x10000); } else { CHECK_VALUE(io.readx.out.nread, 0); } io.readx.in.maxcnt = 0x10001; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); if (lp_parm_bool(-1, "torture", "samba3", False)) { printf("SAMBA3: large read extension\n"); CHECK_VALUE(io.readx.out.nread, 0x10001); } else { CHECK_VALUE(io.readx.out.nread, 0); } } printf("Trying locked region\n"); cli->session->pid++; if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) { printf("Failed to lock file at %d\n", __LINE__); ret = False; goto done; } cli->session->pid--; memset(buf, 0, maxsize); io.readx.in.offset = 0; io.readx.in.mincnt = 100; io.readx.in.maxcnt = 200; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT); if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) { printf("skipping large file tests - CAP_LARGE_FILES not set\n"); goto done; } printf("Trying large offset read\n"); io.readx.in.offset = ((uint64_t)0x2) << 32; io.readx.in.mincnt = 10; io.readx.in.maxcnt = 10; status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, 0); if (NT_STATUS_IS_ERR(smbcli_lock64(cli->tree, fnum, io.readx.in.offset, 1, 0, WRITE_LOCK))) { printf("Failed to lock file at %d\n", __LINE__); ret = False; goto done; } status = smb_raw_read(cli->tree, &io); CHECK_STATUS(status, NT_STATUS_OK); CHECK_VALUE(io.readx.out.nread, 0); done: smbcli_close(cli->tree, fnum); smbcli_deltree(cli->tree, BASEDIR); return ret; }
/* 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; }