📄 nbio.c
字号:
/* TODO: add splitting of writes for servers with signing*//* Unix SMB/CIFS implementation. SMB torture tester Copyright (C) Andrew Tridgell 1997-1998 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 <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "system/time.h"#include "system/filesys.h"#include "lib/util/dlinklist.h"#include "libcli/libcli.h"#include "libcli/raw/libcliraw.h"#include "torture/torture.h"#include "libcli/libcli.h"#include "torture/util.h"#include "torture/nbench/proto.h"extern int nbench_line_count;static int nbio_id = -1;static int nprocs;static bool bypass_io;static struct timeval tv_start, tv_end;static int warmup, timelimit;static int in_cleanup;struct lock_info { struct lock_info *next, *prev; off_t offset; int size;};struct createx_params { char *fname; uint_t create_options; uint_t create_disposition; int handle;};struct ftable { struct ftable *next, *prev; int fd; /* the fd that we got back from the server */ int handle; /* the handle in the load file */ struct createx_params cp; struct lock_info *locks;};static struct ftable *ftable;static struct { double bytes, warmup_bytes; int line; int done; bool connected; double max_latency; struct timeval starttime;} *children;static bool nb_do_createx(struct ftable *f, const char *fname, uint_t create_options, uint_t create_disposition, int handle, NTSTATUS status, bool retry);static bool nb_do_lockx(bool relock, int handle, off_t offset, int size, NTSTATUS status);static void nb_set_createx_params(struct ftable *f, const char *fname, uint_t create_options, uint_t create_disposition, int handle){ struct createx_params *cp = &f->cp; if (fname != NULL) { cp->fname = talloc_strdup(f, fname); if (cp->fname == NULL) { perror("nb_set_createx_params: strdup"); nb_exit(1); } } else { cp->fname = NULL; } cp->create_options = create_options; cp->create_disposition = create_disposition; cp->handle = handle;}static bool nb_reestablish_locks(struct ftable *f){ struct lock_info *linfo = f->locks; while (linfo != NULL) { DEBUG(1,("nb_reestablish_locks: lock for file %d at %lu\n", f->handle, (unsigned long) linfo->offset)); if (!nb_do_lockx(true, f->handle, linfo->offset, linfo->size, NT_STATUS_OK)) { printf("nb_reestablish_locks: failed to get lock for file %s at %lu\n", f->cp.fname, (unsigned long) linfo->offset); return false; } linfo = linfo->next; } return true;}static bool nb_reopen_all_files(void){ struct ftable *f = ftable; while (f != NULL) { DEBUG(1,("-- nb_reopen_all_files: opening %s (handle %d)\n", f->cp.fname, f->cp.handle)); if (!nb_do_createx(f, f->cp.fname, f->cp.create_options, f->cp.create_disposition, f->cp.handle, NT_STATUS_OK, true)) { printf("-- nb_reopen_all_files: failed to open file %s\n", f->cp.fname); return false; } if (!nb_reestablish_locks(f)) { printf("--nb_reopen_all_files: failed to reestablish locks\n"); return false; } f = f->next; } return true;}bool nb_reconnect(struct smbcli_state **cli, struct torture_context *tctx, int client){ children[client].connected = false; if (*cli != NULL) { talloc_free(*cli); } if (!torture_open_connection(cli, tctx, client)) { printf("nb_reconnect: failed to connect\n"); *cli = NULL; return false; } nb_setup(*cli, client); if (!nb_reopen_all_files()) { printf("nb_reconnect: failed to reopen files in client %d\n", client); return false; } return true;}void nbio_target_rate(double rate){ static double last_bytes; static struct timeval last_time; double tdelay; if (last_bytes == 0) { last_bytes = children[nbio_id].bytes; last_time = timeval_current(); return; } tdelay = (children[nbio_id].bytes - last_bytes)/(1.0e6*rate) - timeval_elapsed(&last_time); if (tdelay > 0) { msleep(tdelay*1000); } else { children[nbio_id].max_latency = MAX(children[nbio_id].max_latency, -tdelay); } last_time = timeval_current(); last_bytes = children[nbio_id].bytes;}void nbio_time_reset(void){ children[nbio_id].starttime = timeval_current(); }void nbio_time_delay(double targett){ double elapsed = timeval_elapsed(&children[nbio_id].starttime); if (targett > elapsed) { msleep(1000*(targett - elapsed)); } else if (elapsed - targett > children[nbio_id].max_latency) { children[nbio_id].max_latency = MAX(elapsed - targett, children[nbio_id].max_latency); }}double nbio_result(void){ int i; double total = 0; for (i=0;i<nprocs;i++) { total += children[i].bytes - children[i].warmup_bytes; } return 1.0e-6 * total / timeval_elapsed2(&tv_start, &tv_end);}double nbio_latency(void){ int i; double max_latency = 0; for (i=0;i<nprocs;i++) { if (children[i].max_latency > max_latency) { max_latency = children[i].max_latency; children[i].max_latency = 0; } } return max_latency;}bool nb_tick(void){ return children[nbio_id].done;}void nb_alarm(int sig){ int i; int lines=0; double t; int in_warmup = 0; int num_connected = 0; if (nbio_id != -1) return; for (i=0;i<nprocs;i++) { if (children[i].connected) { num_connected++; } if (children[i].bytes == 0) { in_warmup = 1; } lines += children[i].line; } t = timeval_elapsed(&tv_start); if (!in_warmup && warmup>0 && t > warmup) { tv_start = timeval_current(); warmup = 0; for (i=0;i<nprocs;i++) { children[i].warmup_bytes = children[i].bytes; } goto next; } if (t < warmup) { in_warmup = 1; } else if (!in_warmup && !in_cleanup && t > timelimit) { for (i=0;i<nprocs;i++) { children[i].done = 1; } tv_end = timeval_current(); in_cleanup = 1; } if (t < 1) { goto next; } if (!in_cleanup) { tv_end = timeval_current(); } if (in_warmup) { printf("%4d %8d %.2f MB/sec warmup %.0f sec \n", num_connected, lines/nprocs, nbio_result(), t); } else if (in_cleanup) { printf("%4d %8d %.2f MB/sec cleanup %.0f sec \n", num_connected, lines/nprocs, nbio_result(), t); } else { printf("%4d %8d %.2f MB/sec execute %.0f sec latency %.2f msec \n", num_connected, lines/nprocs, nbio_result(), t, nbio_latency() * 1.0e3); } fflush(stdout);next: signal(SIGALRM, nb_alarm); alarm(1); }void nbio_shmem(int n, int t_timelimit, int t_warmup){ nprocs = n; children = shm_setup(sizeof(*children) * nprocs); if (!children) { printf("Failed to setup shared memory!\n"); nb_exit(1); } memset(children, 0, sizeof(*children) * nprocs); timelimit = t_timelimit; warmup = t_warmup; in_cleanup = 0; tv_start = timeval_current();}static struct lock_info* find_lock(struct lock_info *linfo, off_t offset, int size){ while (linfo != NULL) { if (linfo->offset == offset && linfo->size == size) { return linfo; } linfo = linfo->next; } return NULL;}static struct ftable *find_ftable(int handle){ struct ftable *f; for (f=ftable;f;f=f->next) { if (f->handle == handle) return f; } return NULL;}static int find_handle(int handle, struct ftable **f_ret){ struct ftable *f; if (f_ret != NULL) *f_ret = NULL; children[nbio_id].line = nbench_line_count; f = find_ftable(handle); if (f) { if (f_ret != NULL) *f_ret = f; return f->fd; } printf("(%d) ERROR: handle %d was not found\n", nbench_line_count, handle); nb_exit(1); return -1; /* Not reached */}static struct smbcli_state *c;/* a handler function for oplock break requests*/static bool oplock_handler(struct smbcli_transport *transport, uint16_t tid, uint16_t fnum, uint8_t level, void *private){ struct smbcli_tree *tree = (struct smbcli_tree *)private; return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);}void nb_setup(struct smbcli_state *cli, int id){ nbio_id = id; c = cli; if (bypass_io) printf("skipping I/O\n"); if (cli) { smbcli_oplock_handler(cli->transport, oplock_handler, cli->tree); } children[id].connected = true;}static bool check_status(const char *op, NTSTATUS status, NTSTATUS ret){ if ((NT_STATUS_EQUAL(ret, NT_STATUS_END_OF_FILE) || NT_STATUS_EQUAL(ret, NT_STATUS_NET_WRITE_FAULT) || NT_STATUS_EQUAL(ret, NT_STATUS_CONNECTION_RESET)) && !NT_STATUS_EQUAL (status, ret)) { return false; } if (!NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(ret)) { printf("[%d] Error: %s should have failed with %s\n", nbench_line_count, op, nt_errstr(status)); nb_exit(1); } if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ret)) { printf("[%d] Error: %s should have succeeded - %s\n", nbench_line_count, op, nt_errstr(ret)); nb_exit(1); } if (!NT_STATUS_EQUAL(status, ret)) { printf("[%d] Warning: got status %s but expected %s\n", nbench_line_count, nt_errstr(ret), nt_errstr(status)); } return true;}bool nb_unlink(const char *fname, int attr, NTSTATUS status, bool retry){ union smb_unlink io; NTSTATUS ret; io.unlink.in.pattern = fname; io.unlink.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN; if (strchr(fname, '*') == 0) { io.unlink.in.attrib |= FILE_ATTRIBUTE_DIRECTORY; } ret = smb_raw_unlink(c->tree, &io); if (!retry) return check_status("Unlink", status, ret); return true;}static bool nb_do_createx(struct ftable *f, const char *fname, uint_t create_options, uint_t create_disposition, int handle, NTSTATUS status, bool retry){ union smb_open io; uint32_t desired_access; NTSTATUS ret; TALLOC_CTX *mem_ctx; uint_t flags = 0; mem_ctx = talloc_init("raw_open"); if (create_options & NTCREATEX_OPTIONS_DIRECTORY) { desired_access = SEC_FILE_READ_DATA; } else { desired_access = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_ATTRIBUTE; flags = NTCREATEX_FLAGS_EXTENDED | NTCREATEX_FLAGS_REQUEST_OPLOCK | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK; } io.ntcreatex.level = RAW_OPEN_NTCREATEX; io.ntcreatex.in.flags = flags; io.ntcreatex.in.root_fid = 0; io.ntcreatex.in.access_mask = desired_access; io.ntcreatex.in.file_attr = 0; io.ntcreatex.in.alloc_size = 0; io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE; io.ntcreatex.in.open_disposition = create_disposition; io.ntcreatex.in.create_options = create_options; io.ntcreatex.in.impersonation = 0; io.ntcreatex.in.security_flags = 0; io.ntcreatex.in.fname = fname;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -