root/source4/torture/raw/pingpong.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lock_byte
  2. unlock_byte
  3. write_byte
  4. read_byte
  5. start_timer
  6. end_timer
  7. torture_ping_pong

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    ping pong test
   5 
   6    Copyright (C) Ronnie Sahlberg 2007
   7 
   8    Significantly based on and borrowed from lockbench.c by
   9    Copyright (C) Andrew Tridgell 2006
  10    
  11    This program is free software; you can redistribute it and/or modify
  12    it under the terms of the GNU General Public License as published by
  13    the Free Software Foundation; either version 3 of the License, or
  14    (at your option) any later version.
  15    
  16    This program is distributed in the hope that it will be useful,
  17    but WITHOUT ANY WARRANTY; without even the implied warranty of
  18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19    GNU General Public License for more details.
  20    
  21    You should have received a copy of the GNU General Public License
  22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  23 */
  24 
  25 /*
  26    filename is specified by
  27          --option=torture:filename=...
  28 
  29    number of locks is specified by
  30          --option=torture:num_locks=...
  31 
  32    locktimeout is specified in ms by
  33          --option=torture:locktimeout=...
  34 
  35        default is 100 seconds
  36        if set to 0 pingpong will instead loop trying the lock operation
  37        over and over until it completes.
  38 
  39    reading from the file can be enabled with
  40          --option=torture:read=true
  41 
  42    writing to the file can be enabled with
  43          --option=torture:write=true
  44 
  45 */
  46 #include "includes.h"
  47 #include "torture/torture.h"
  48 #include "libcli/raw/libcliraw.h"
  49 #include "system/time.h"
  50 #include "system/filesys.h"
  51 #include "libcli/libcli.h"
  52 #include "torture/util.h"
  53 
  54 static void lock_byte(struct smbcli_state *cli, int fd, int offset, int lock_timeout)
     /* [<][>][^][v][top][bottom][index][help] */
  55 {
  56         union smb_lock io;
  57         struct smb_lock_entry lock;
  58         NTSTATUS status;
  59 
  60 try_again:
  61         ZERO_STRUCT(lock);
  62         io.lockx.in.ulock_cnt = 0;
  63         io.lockx.in.lock_cnt = 1;
  64 
  65         lock.count = 1;
  66         lock.offset = offset;
  67         lock.pid = cli->tree->session->pid;
  68         io.lockx.level = RAW_LOCK_LOCKX;
  69         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
  70         io.lockx.in.timeout = lock_timeout;
  71         io.lockx.in.locks = &lock;
  72         io.lockx.in.file.fnum = fd;
  73 
  74         status = smb_raw_lock(cli->tree, &io);
  75 
  76         /* If we dont use timeouts and we got file lock conflict
  77            just try the lock again.
  78         */
  79         if (lock_timeout==0) {
  80                 if ( (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status))
  81                    ||(NT_STATUS_EQUAL(NT_STATUS_LOCK_NOT_GRANTED, status)) ) {
  82                         goto try_again;
  83                 }
  84         }
  85 
  86         if (!NT_STATUS_IS_OK(status)) {
  87                 DEBUG(0,("Lock failed\n"));
  88                 exit(1);
  89         }
  90 }
  91 
  92 static void unlock_byte(struct smbcli_state *cli, int fd, int offset)
     /* [<][>][^][v][top][bottom][index][help] */
  93 {
  94         union smb_lock io;
  95         struct smb_lock_entry lock;
  96         NTSTATUS status;
  97 
  98         ZERO_STRUCT(lock);
  99         io.lockx.in.ulock_cnt = 1;
 100         io.lockx.in.lock_cnt = 0;
 101 
 102         lock.count = 1;
 103         lock.offset = offset;
 104         lock.pid = cli->tree->session->pid;
 105         io.lockx.level = RAW_LOCK_LOCKX;
 106         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
 107         io.lockx.in.timeout = 100000;
 108         io.lockx.in.locks = &lock;
 109         io.lockx.in.file.fnum = fd;
 110 
 111         status = smb_raw_lock(cli->tree, &io);
 112 
 113         if (!NT_STATUS_IS_OK(status)) {
 114                 DEBUG(0,("Unlock failed\n"));
 115                 exit(1);
 116         }
 117 }
 118 
 119 static void write_byte(struct smbcli_state *cli, int fd, uint8_t c, int offset)
     /* [<][>][^][v][top][bottom][index][help] */
 120 {
 121         union smb_write io;
 122         NTSTATUS status;
 123 
 124         io.generic.level = RAW_WRITE_WRITEX;
 125         io.writex.in.file.fnum = fd;
 126         io.writex.in.offset = offset;
 127         io.writex.in.wmode = 0;
 128         io.writex.in.remaining = 0;
 129         io.writex.in.count = 1;
 130         io.writex.in.data = &c;
 131 
 132         status = smb_raw_write(cli->tree, &io);
 133         if (!NT_STATUS_IS_OK(status)) {
 134                 printf("write failed\n");
 135                 exit(1);
 136         }
 137 }       
 138 
 139 static void read_byte(struct smbcli_state *cli, int fd, uint8_t *c, int offset)
     /* [<][>][^][v][top][bottom][index][help] */
 140 {
 141         union smb_read io;
 142         NTSTATUS status;
 143 
 144         io.generic.level = RAW_READ_READX;
 145         io.readx.in.file.fnum = fd;
 146         io.readx.in.mincnt = 1;
 147         io.readx.in.maxcnt = 1;
 148         io.readx.in.offset = offset;
 149         io.readx.in.remaining = 0;
 150         io.readx.in.read_for_execute = false;
 151         io.readx.out.data = c;
 152 
 153         status = smb_raw_read(cli->tree, &io);
 154         if (!NT_STATUS_IS_OK(status)) {
 155                 printf("read failed\n");
 156                 exit(1);
 157         }
 158 }       
 159 
 160 
 161 static struct timeval tp1, tp2;
 162 
 163 static void start_timer(void)
     /* [<][>][^][v][top][bottom][index][help] */
 164 {
 165         gettimeofday(&tp1, NULL);
 166 }
 167 
 168 static double end_timer(void)
     /* [<][>][^][v][top][bottom][index][help] */
 169 {
 170         gettimeofday(&tp2, NULL);
 171         return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) - 
 172                 (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
 173 }
 174 
 175 /* 
 176    ping pong
 177 */
 178 bool torture_ping_pong(struct torture_context *torture)
     /* [<][>][^][v][top][bottom][index][help] */
 179 {
 180         const char *fn;
 181         int num_locks;
 182         TALLOC_CTX *mem_ctx = talloc_new(torture);
 183         static bool do_reads;
 184         static bool do_writes;
 185         int lock_timeout;
 186         int fd;
 187         struct smbcli_state *cli;
 188         int i;
 189         uint8_t incr=0, last_incr=0;
 190         uint8_t *val;
 191         int count, loops;
 192 
 193         fn = torture_setting_string(torture, "filename", NULL);
 194         if (fn == NULL) {
 195                 DEBUG(0,("You must specify the filename using --option=torture:filename=...\n"));
 196                 return false;
 197         }
 198 
 199         num_locks = torture_setting_int(torture, "num_locks", -1);
 200         if (num_locks == -1) {
 201                 DEBUG(0,("You must specify num_locks using --option=torture:num_locks=...\n"));
 202                 return false;
 203         }
 204 
 205         do_reads     = torture_setting_bool(torture, "read", false);
 206         do_writes    = torture_setting_bool(torture, "write", false);
 207         lock_timeout =  torture_setting_int(torture, "lock_timeout", 100000);
 208 
 209         if (!torture_open_connection(&cli, torture, 0)) {
 210                 DEBUG(0,("Could not open connection\n"));
 211                 return false;
 212         }
 213 
 214         fd = smbcli_open(cli->tree, fn, O_RDWR|O_CREAT, DENY_NONE);
 215         if (fd == -1) {
 216                 printf("Failed to open %s\n", fn);
 217                 exit(1);
 218         }
 219 
 220         write_byte(cli, fd, 0, num_locks);
 221         lock_byte(cli, fd, 0, lock_timeout);
 222 
 223 
 224         start_timer();
 225         val = talloc_zero_array(mem_ctx, uint8_t, num_locks);
 226         i = 0;
 227         count = 0;
 228         loops = 0;
 229         while (1) {
 230                 lock_byte(cli, fd, (i+1)%num_locks, lock_timeout);
 231 
 232                 if (do_reads) {
 233                         uint8_t c;
 234                         read_byte(cli, fd, &c, i);
 235                         incr   = c-val[i];
 236                         val[i] = c;                     
 237                 }
 238 
 239                 if (do_writes) {
 240                         uint8_t c = val[i] + 1;
 241                         write_byte(cli, fd, c, i);
 242                 }
 243 
 244                 unlock_byte(cli, fd, i);
 245 
 246                 i = (i+1)%num_locks;
 247                 count++;
 248                 if (loops>num_locks && incr!=last_incr) {
 249                         last_incr = incr;
 250                         printf("data increment = %u\n", incr);
 251                         fflush(stdout);
 252                 }
 253                 if (end_timer() > 1.0) {
 254                         printf("%8u locks/sec\r", 
 255                                (unsigned)(2*count/end_timer()));
 256                         fflush(stdout);
 257                         start_timer();
 258                         count=0;
 259                 }
 260                 loops++;
 261         }
 262 
 263         talloc_free(mem_ctx);
 264         return true;
 265 }
 266 

/* [<][>][^][v][top][bottom][index][help] */