r23531: added optional latency reporting in BENCH-NBENCH. To use it, you need
[samba.git] / source / torture / nbench / nbio.c
index 5ef791037a779ee4a46c555a3be1d6662c369c5f..a382c92ceb9ed2da5cb7caa0ccc01be3edceb554 100644 (file)
@@ -1,4 +1,7 @@
-#define NBDEBUG 0
+/*
+  TODO: add splitting of writes for servers with signing
+*/
+
 
 /* 
    Unix SMB/CIFS implementation.
 
 #include "includes.h"
 #include "system/time.h"
-
-#define MAX_FILES 100
+#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"
 
 extern int nbench_line_count;
-static int nbio_id;
+static int nbio_id = -1;
 static int nprocs;
 static BOOL bypass_io;
-static int warmup;
+static struct timeval tv_start, tv_end;
+static int warmup, timelimit;
+static int in_cleanup;
 
 struct ftable {
        struct ftable *next, *prev;
@@ -40,67 +50,120 @@ struct ftable {
 static struct ftable *ftable;
 
 static struct {
-       double bytes_in, bytes_out;
+       double bytes, warmup_bytes;
        int line;
        int done;
+       double max_latency;
+       struct timeval starttime;
 } *children;
 
-double nbio_total(void)
+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 = elapsed - targett;
+       }
+}
+
+double nbio_result(void)
 {
        int i;
        double total = 0;
        for (i=0;i<nprocs;i++) {
-               total += children[i].bytes_out + children[i].bytes_in;
+               total += children[i].bytes - children[i].warmup_bytes;
        }
-       return total;
+       return 1.0e-6 * total / timeval_elapsed2(&tv_start, &tv_end);
 }
 
-void nb_warmup_done(void)
+double nbio_latency(void)
 {
-       children[nbio_id].bytes_out = 0;
-       children[nbio_id].bytes_in = 0;
+       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, num_clients=0;
+       int lines=0;
        double t;
+       int in_warmup = 0;
 
        if (nbio_id != -1) return;
 
        for (i=0;i<nprocs;i++) {
+               if (children[i].bytes == 0) {
+                       in_warmup = 1;
+               }
                lines += children[i].line;
-               if (!children[i].done) num_clients++;
        }
 
-       t = end_timer();
+       t = timeval_elapsed(&tv_start);
 
-       if (warmup) {
-               printf("%4d  %8d  %.2f MB/sec  warmup %.0f sec   \n", 
-                      num_clients, lines/nprocs, 
-                      1.0e-6 * nbio_total() / t, 
-                      t);
-       } else {
-               printf("%4d  %8d  %.2f MB/sec  execute %.0f sec   \n", 
-                      num_clients, lines/nprocs, 
-                      1.0e-6 * nbio_total() / t, 
-                      t);
+       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 (warmup && t >= warmup) {
-               start_timer();
-               warmup = 0;
+       if (in_warmup) {
+               printf("%4d  %8d  %.2f MB/sec  warmup %.0f sec   \n", 
+                      nprocs, lines/nprocs, 
+                      nbio_result(), t);
+       } else if (in_cleanup) {
+               printf("%4d  %8d  %.2f MB/sec  cleanup %.0f sec   \n", 
+                      nprocs, lines/nprocs, 
+                      nbio_result(), t);
+       } else {
+               printf("%4d  %8d  %.2f MB/sec  execute %.0f sec  latency %.2f msec \n", 
+                      nprocs, lines/nprocs, 
+                      nbio_result(), t, nbio_latency() * 1.0e3);
        }
 
        fflush(stdout);
-
+next:
        signal(SIGALRM, nb_alarm);
        alarm(1);       
 }
 
-void nbio_shmem(int n)
+void nbio_shmem(int n, int t_timelimit, int t_warmup)
 {
        nprocs = n;
        children = shm_setup(sizeof(*children) * nprocs);
@@ -108,6 +171,11 @@ void nbio_shmem(int n)
                printf("Failed to setup shared memory!\n");
                exit(1);
        }
+       memset(children, 0, sizeof(*children) * nprocs);
+       timelimit = t_timelimit;
+       warmup = t_warmup;
+       in_cleanup = 0;
+       tv_start = timeval_current();
 }
 
 static struct ftable *find_ftable(int handle)
@@ -144,21 +212,17 @@ 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)
+static BOOL oplock_handler(struct smbcli_transport *transport, uint16_t tid, 
+                          uint16_t fnum, uint8_t level, void *private)
 {
        struct smbcli_tree *tree = private;
-       return smbcli_oplock_ack(tree, fnum, level);
+       return smbcli_oplock_ack(tree, fnum, OPLOCK_BREAK_TO_NONE);
 }
 
-void nb_setup(struct smbcli_state *cli, int id, int warmupt)
+void nb_setup(struct smbcli_state *cli, int id)
 {
-       warmup = warmupt;
        nbio_id = id;
        c = cli;
-       start_timer();
-       if (children) {
-               children[nbio_id].done = 0;
-       }
        if (bypass_io)
                printf("skipping I/O\n");
 
@@ -191,14 +255,14 @@ static void check_status(const char *op, NTSTATUS status, NTSTATUS ret)
 
 void nb_unlink(const char *fname, int attr, NTSTATUS status)
 {
-       struct smb_unlink io;
+       union smb_unlink io;
        NTSTATUS ret;
 
-       io.in.pattern = fname;
+       io.unlink.in.pattern = fname;
 
-       io.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
+       io.unlink.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
        if (strchr(fname, '*') == 0) {
-               io.in.attrib |= FILE_ATTRIBUTE_DIRECTORY;
+               io.unlink.in.attrib |= FILE_ATTRIBUTE_DIRECTORY;
        }
 
        ret = smb_raw_unlink(c->tree, &io);
@@ -221,13 +285,13 @@ void nb_createx(const char *fname,
        mem_ctx = talloc_init("raw_open");
 
        if (create_options & NTCREATEX_OPTIONS_DIRECTORY) {
-               desired_access = SA_RIGHT_FILE_READ_DATA;
+               desired_access = SEC_FILE_READ_DATA;
        } else {
                desired_access = 
-                       SA_RIGHT_FILE_READ_DATA | 
-                       SA_RIGHT_FILE_WRITE_DATA |
-                       SA_RIGHT_FILE_READ_ATTRIBUTES |
-                       SA_RIGHT_FILE_WRITE_ATTRIBUTES;
+                       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;
@@ -248,25 +312,25 @@ void nb_createx(const char *fname,
 
        ret = smb_raw_open(c->tree, mem_ctx, &io);
 
-       talloc_destroy(mem_ctx);
+       talloc_free(mem_ctx);
 
        check_status("NTCreateX", status, ret);
 
        if (!NT_STATUS_IS_OK(ret)) return;
 
-       f = malloc(sizeof(struct ftable));
+       f = malloc_p(struct ftable);
        f->handle = handle;
-       f->fd = io.ntcreatex.out.fnum;
+       f->fd = io.ntcreatex.out.file.fnum;
 
        DLIST_ADD_END(ftable, f, struct ftable *);
 }
 
-void nb_writex(int handle, int offset, int size, int ret_size, NTSTATUS status)
+void nb_writex(int handle, off_t offset, int size, int ret_size, NTSTATUS status)
 {
        union smb_write io;
        int i;
        NTSTATUS ret;
-       char *buf;
+       uint8_t *buf;
 
        i = find_handle(handle);
 
@@ -276,7 +340,7 @@ void nb_writex(int handle, int offset, int size, int ret_size, NTSTATUS status)
        memset(buf, 0xab, size);
 
        io.writex.level = RAW_WRITE_WRITEX;
-       io.writex.in.fnum = i;
+       io.writex.in.file.fnum = i;
        io.writex.in.wmode = 0;
        io.writex.in.remaining = 0;
        io.writex.in.offset = offset;
@@ -295,15 +359,15 @@ void nb_writex(int handle, int offset, int size, int ret_size, NTSTATUS status)
                       io.writex.out.nwritten, ret_size);
        }       
 
-       children[nbio_id].bytes_out += ret_size;
+       children[nbio_id].bytes += ret_size;
 }
 
-void nb_write(int handle, int offset, int size, int ret_size, NTSTATUS status)
+void nb_write(int handle, off_t offset, int size, int ret_size, NTSTATUS status)
 {
        union smb_write io;
        int i;
        NTSTATUS ret;
-       char *buf;
+       uint8_t *buf;
 
        i = find_handle(handle);
 
@@ -314,7 +378,7 @@ void nb_write(int handle, int offset, int size, int ret_size, NTSTATUS status)
        memset(buf, 0x12, size);
 
        io.write.level = RAW_WRITE_WRITE;
-       io.write.in.fnum = i;
+       io.write.in.file.fnum = i;
        io.write.in.remaining = 0;
        io.write.in.offset = offset;
        io.write.in.count = size;
@@ -332,11 +396,11 @@ void nb_write(int handle, int offset, int size, int ret_size, NTSTATUS status)
                       io.write.out.nwritten, ret_size);
        }       
 
-       children[nbio_id].bytes_out += ret_size;
+       children[nbio_id].bytes += ret_size;
 }
 
 
-void nb_lockx(int handle, uint_t offset, int size, NTSTATUS status)
+void nb_lockx(int handle, off_t offset, int size, NTSTATUS status)
 {
        union smb_lock io;
        int i;
@@ -350,7 +414,7 @@ void nb_lockx(int handle, uint_t offset, int size, NTSTATUS status)
        lck.count = size;
 
        io.lockx.level = RAW_LOCK_LOCKX;
-       io.lockx.in.fnum = i;
+       io.lockx.in.file.fnum = i;
        io.lockx.in.mode = 0;
        io.lockx.in.timeout = 0;
        io.lockx.in.ulock_cnt = 0;
@@ -376,7 +440,7 @@ void nb_unlockx(int handle, uint_t offset, int size, NTSTATUS status)
        lck.count = size;
 
        io.lockx.level = RAW_LOCK_LOCKX;
-       io.lockx.in.fnum = i;
+       io.lockx.in.file.fnum = i;
        io.lockx.in.mode = 0;
        io.lockx.in.timeout = 0;
        io.lockx.in.ulock_cnt = 1;
@@ -388,12 +452,12 @@ void nb_unlockx(int handle, uint_t offset, int size, NTSTATUS status)
        check_status("UnlockX", status, ret);
 }
 
-void nb_readx(int handle, int offset, int size, int ret_size, NTSTATUS status)
+void nb_readx(int handle, off_t offset, int size, int ret_size, NTSTATUS status)
 {
        union smb_read io;
        int i;
        NTSTATUS ret;
-       char *buf;
+       uint8_t *buf;
 
        i = find_handle(handle);
 
@@ -402,13 +466,14 @@ void nb_readx(int handle, int offset, int size, int ret_size, NTSTATUS status)
        buf = malloc(size);
 
        io.readx.level = RAW_READ_READX;
-       io.readx.in.fnum = i;
+       io.readx.in.file.fnum = i;
        io.readx.in.offset    = offset;
        io.readx.in.mincnt    = size;
        io.readx.in.maxcnt    = size;
        io.readx.in.remaining = 0;
+       io.readx.in.read_for_execute = False;
        io.readx.out.data     = buf;
-               
+       
        ret = smb_raw_read(c->tree, &io);
 
        free(buf);
@@ -422,7 +487,7 @@ void nb_readx(int handle, int offset, int size, int ret_size, NTSTATUS status)
                exit(1);
        }       
 
-       children[nbio_id].bytes_in += ret_size;
+       children[nbio_id].bytes += ret_size;
 }
 
 void nb_close(int handle, NTSTATUS status)
@@ -434,7 +499,7 @@ void nb_close(int handle, NTSTATUS status)
        i = find_handle(handle);
 
        io.close.level = RAW_CLOSE_CLOSE;
-       io.close.in.fnum = i;
+       io.close.in.file.fnum = i;
        io.close.in.write_time = 0;
 
        ret = smb_raw_close(c->tree, &io);
@@ -496,11 +561,11 @@ void nb_qpathinfo(const char *fname, int level, NTSTATUS status)
        mem_ctx = talloc_init("nb_qpathinfo");
 
        io.generic.level = level;
-       io.generic.in.fname = fname;
+       io.generic.in.file.path = fname;
 
        ret = smb_raw_pathinfo(c->tree, mem_ctx, &io);
 
-       talloc_destroy(mem_ctx);
+       talloc_free(mem_ctx);
 
        check_status("Pathinfo", status, ret);
 }
@@ -518,11 +583,11 @@ void nb_qfileinfo(int fnum, int level, NTSTATUS status)
        mem_ctx = talloc_init("nb_qfileinfo");
 
        io.generic.level = level;
-       io.generic.in.fnum = i;
+       io.generic.in.file.fnum = i;
 
        ret = smb_raw_fileinfo(c->tree, mem_ctx, &io);
 
-       talloc_destroy(mem_ctx);
+       talloc_free(mem_ctx);
 
        check_status("Fileinfo", status, ret);
 }
@@ -543,7 +608,7 @@ void nb_sfileinfo(int fnum, int level, NTSTATUS status)
        i = find_handle(fnum);
 
        io.generic.level = level;
-       io.generic.file.fnum = i;
+       io.generic.in.file.fnum = i;
        unix_to_nt_time(&io.basic_info.in.create_time, time(NULL));
        unix_to_nt_time(&io.basic_info.in.access_time, 0);
        unix_to_nt_time(&io.basic_info.in.write_time, 0);
@@ -566,13 +631,13 @@ void nb_qfsinfo(int level, NTSTATUS status)
        io.generic.level = level;
        ret = smb_raw_fsinfo(c->tree, mem_ctx, &io);
 
-       talloc_destroy(mem_ctx);
+       talloc_free(mem_ctx);
        
        check_status("Fsinfo", status, ret);    
 }
 
 /* callback function used for trans2 search */
-static BOOL findfirst_callback(void *private, union smb_search_data *file)
+static BOOL findfirst_callback(void *private, const union smb_search_data *file)
 {
        return True;
 }
@@ -585,7 +650,8 @@ void nb_findfirst(const char *mask, int level, int maxcnt, int count, NTSTATUS s
 
        mem_ctx = talloc_init("smbcli_dskattr");
 
-       io.t2ffirst.level = level;
+       io.t2ffirst.level = RAW_SEARCH_TRANS2;
+       io.t2ffirst.data_level = level;
        io.t2ffirst.in.max_count = maxcnt;
        io.t2ffirst.in.search_attrib = FILE_ATTRIBUTE_DIRECTORY;
        io.t2ffirst.in.pattern = mask;
@@ -594,7 +660,7 @@ void nb_findfirst(const char *mask, int level, int maxcnt, int count, NTSTATUS s
                        
        ret = smb_raw_search_first(c->tree, mem_ctx, &io, NULL, findfirst_callback);
 
-       talloc_destroy(mem_ctx);
+       talloc_free(mem_ctx);
 
        check_status("Search", status, ret);
 
@@ -607,12 +673,13 @@ void nb_findfirst(const char *mask, int level, int maxcnt, int count, NTSTATUS s
 
 void nb_flush(int fnum, NTSTATUS status)
 {
-       struct smb_flush io;
+       union smb_flush io;
        NTSTATUS ret;
        int i;
        i = find_handle(fnum);
 
-       io.in.fnum = i;
+       io.flush.level          = RAW_FLUSH_FLUSH;
+       io.flush.in.file.fnum   = i;
 
        ret = smb_raw_flush(c->tree, &io);
 
@@ -621,8 +688,7 @@ void nb_flush(int fnum, NTSTATUS status)
 
 void nb_sleep(int usec, NTSTATUS status)
 {
-       (void)status;
-       sys_usleep(usec);
+       usleep(usec);
 }
 
 void nb_deltree(const char *dname)
@@ -647,12 +713,3 @@ void nb_deltree(const char *dname)
        smbcli_rmdir(c->tree, dname);
 }
 
-void nb_cleanup(const char *cname)
-{
-       char *dname = NULL;
-       asprintf(&dname, "\\clients\\%s", cname);
-       nb_deltree(dname);
-       free(dname);
-       smbcli_rmdir(c->tree, "clients");
-       children[nbio_id].done = 1;
-}