2007-08-29 05:45:24 +00:00
/*
Unix SMB / CIFS implementation .
ping pong test
2007-08-29 06:58:25 +00:00
Copyright ( C ) Ronnie Sahlberg 2007
Significantly based on and borrowed from lockbench . c by
Copyright ( C ) Andrew Tridgell 2006
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/>.
*/
/*
2007-08-29 05:45:24 +00:00
filename is specified by
- - option = torture : filename = . . .
number of locks is specified by
- - option = torture : num_locks = . . .
locktimeout is specified in ms by
- - option = torture : locktimeout = . . .
default is 100 seconds
if set to 0 pingpong will instead loop trying the lock operation
over and over until it completes .
reading from the file can be enabled with
2007-10-06 22:28:14 +00:00
- - option = torture : read = true
2007-08-29 05:45:24 +00:00
writing to the file can be enabled with
2007-10-06 22:28:14 +00:00
- - option = torture : write = true
2007-08-29 05:45:24 +00:00
*/
# include "includes.h"
# include "torture/torture.h"
# include "libcli/raw/libcliraw.h"
# include "system/time.h"
# include "system/filesys.h"
# include "libcli/libcli.h"
# include "torture/util.h"
2007-09-08 12:42:09 +00:00
# include "param/param.h"
2007-08-29 05:45:24 +00:00
2007-09-08 16:46:30 +00:00
static void lock_byte ( struct smbcli_state * cli , int fd , int offset , int lock_timeout )
2007-08-29 05:45:24 +00:00
{
union smb_lock io ;
struct smb_lock_entry lock ;
2007-08-29 06:58:25 +00:00
NTSTATUS status ;
2007-08-29 05:45:24 +00:00
2007-08-29 06:58:25 +00:00
try_again :
ZERO_STRUCT ( lock ) ;
io . lockx . in . ulock_cnt = 0 ;
io . lockx . in . lock_cnt = 1 ;
2007-08-29 05:45:24 +00:00
2007-08-29 06:58:25 +00:00
lock . count = 1 ;
lock . offset = offset ;
lock . pid = cli - > tree - > session - > pid ;
io . lockx . level = RAW_LOCK_LOCKX ;
io . lockx . in . mode = LOCKING_ANDX_LARGE_FILES ;
io . lockx . in . timeout = lock_timeout ;
io . lockx . in . locks = & lock ;
io . lockx . in . file . fnum = fd ;
status = smb_raw_lock ( cli - > tree , & io ) ;
/* If we dont use timeouts and we got file lock conflict
just try the lock again .
*/
if ( lock_timeout = = 0 ) {
if ( ( NT_STATUS_EQUAL ( NT_STATUS_FILE_LOCK_CONFLICT , status ) )
| | ( NT_STATUS_EQUAL ( NT_STATUS_LOCK_NOT_GRANTED , status ) ) ) {
goto try_again ;
2007-08-29 05:45:24 +00:00
}
}
2007-08-29 06:58:25 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Lock failed \n " ) ) ;
exit ( 1 ) ;
2007-08-29 05:45:24 +00:00
}
2007-08-29 06:58:25 +00:00
}
2007-08-29 05:45:24 +00:00
2007-09-08 16:46:30 +00:00
static void unlock_byte ( struct smbcli_state * cli , int fd , int offset )
2007-08-29 06:58:25 +00:00
{
union smb_lock io ;
struct smb_lock_entry lock ;
NTSTATUS status ;
2007-08-29 05:45:24 +00:00
2007-08-29 06:58:25 +00:00
ZERO_STRUCT ( lock ) ;
io . lockx . in . ulock_cnt = 1 ;
io . lockx . in . lock_cnt = 0 ;
lock . count = 1 ;
lock . offset = offset ;
lock . pid = cli - > tree - > session - > pid ;
2007-08-29 05:45:24 +00:00
io . lockx . level = RAW_LOCK_LOCKX ;
io . lockx . in . mode = LOCKING_ANDX_LARGE_FILES ;
2007-08-29 06:58:25 +00:00
io . lockx . in . timeout = 100000 ;
2007-08-29 05:45:24 +00:00
io . lockx . in . locks = & lock ;
2007-08-29 06:58:25 +00:00
io . lockx . in . file . fnum = fd ;
2007-08-29 05:45:24 +00:00
2007-08-29 06:58:25 +00:00
status = smb_raw_lock ( cli - > tree , & io ) ;
2007-08-29 05:45:24 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-29 06:58:25 +00:00
DEBUG ( 0 , ( " Unlock failed \n " ) ) ;
2007-08-29 05:45:24 +00:00
exit ( 1 ) ;
}
}
2007-09-08 16:46:30 +00:00
static void write_byte ( struct smbcli_state * cli , int fd , uint8_t c , int offset )
2007-08-29 05:45:24 +00:00
{
union smb_write io ;
2007-08-29 06:58:25 +00:00
NTSTATUS status ;
2007-08-29 05:45:24 +00:00
io . generic . level = RAW_WRITE_WRITEX ;
2007-08-29 06:58:25 +00:00
io . writex . in . file . fnum = fd ;
io . writex . in . offset = offset ;
2007-08-29 05:45:24 +00:00
io . writex . in . wmode = 0 ;
io . writex . in . remaining = 0 ;
io . writex . in . count = 1 ;
2007-08-29 06:58:25 +00:00
io . writex . in . data = & c ;
2007-08-29 05:45:24 +00:00
2007-08-29 06:58:25 +00:00
status = smb_raw_write ( cli - > tree , & io ) ;
2007-08-29 05:45:24 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-29 06:58:25 +00:00
printf ( " write failed \n " ) ;
2007-08-29 05:45:24 +00:00
exit ( 1 ) ;
}
2007-08-29 06:58:25 +00:00
}
2007-08-29 05:45:24 +00:00
2007-09-08 16:46:30 +00:00
static void read_byte ( struct smbcli_state * cli , int fd , uint8_t * c , int offset )
2007-08-29 05:45:24 +00:00
{
union smb_read io ;
2007-08-29 06:58:25 +00:00
NTSTATUS status ;
2007-08-29 05:45:24 +00:00
io . generic . level = RAW_READ_READX ;
2007-08-29 06:58:25 +00:00
io . readx . in . file . fnum = fd ;
2007-08-29 05:45:24 +00:00
io . readx . in . mincnt = 1 ;
io . readx . in . maxcnt = 1 ;
2007-08-29 06:58:25 +00:00
io . readx . in . offset = offset ;
2007-08-29 05:45:24 +00:00
io . readx . in . remaining = 0 ;
2007-10-06 22:28:14 +00:00
io . readx . in . read_for_execute = false ;
2007-08-29 06:58:25 +00:00
io . readx . out . data = c ;
2007-08-29 05:45:24 +00:00
2007-08-29 06:58:25 +00:00
status = smb_raw_read ( cli - > tree , & io ) ;
2007-08-29 05:45:24 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-29 06:58:25 +00:00
printf ( " read failed \n " ) ;
exit ( 1 ) ;
2007-08-29 05:45:24 +00:00
}
2007-08-29 06:58:25 +00:00
}
2007-08-29 05:45:24 +00:00
2007-08-29 06:58:25 +00:00
static struct timeval tp1 , tp2 ;
2007-08-29 05:45:24 +00:00
2007-08-29 06:58:25 +00:00
static void start_timer ( void )
{
gettimeofday ( & tp1 , NULL ) ;
2007-08-29 05:45:24 +00:00
}
2007-08-29 06:58:25 +00:00
static double end_timer ( void )
2007-08-29 05:45:24 +00:00
{
2007-08-29 06:58:25 +00:00
gettimeofday ( & tp2 , NULL ) ;
return ( tp2 . tv_sec + ( tp2 . tv_usec * 1.0e-6 ) ) -
( tp1 . tv_sec + ( tp1 . tv_usec * 1.0e-6 ) ) ;
2007-08-29 05:45:24 +00:00
}
/*
ping pong
*/
2007-09-08 16:46:30 +00:00
bool torture_ping_pong ( struct torture_context * torture )
2007-08-29 05:45:24 +00:00
{
const char * fn ;
2007-08-29 06:58:25 +00:00
int num_locks ;
2007-08-29 05:45:24 +00:00
TALLOC_CTX * mem_ctx = talloc_new ( torture ) ;
2007-10-06 22:28:14 +00:00
static bool do_reads ;
static bool do_writes ;
2007-08-29 06:58:25 +00:00
int lock_timeout ;
int fd ;
2007-08-29 05:45:24 +00:00
struct smbcli_state * cli ;
2007-08-29 06:58:25 +00:00
int i ;
uint8_t incr = 0 , last_incr = 0 ;
uint8_t * val ;
int count , loops ;
2007-08-29 05:45:24 +00:00
2007-09-29 18:00:19 +00:00
fn = lp_parm_string ( global_loadparm , NULL , " torture " , " filename " ) ;
2007-08-29 05:45:24 +00:00
if ( fn = = NULL ) {
DEBUG ( 0 , ( " You must specify the filename using --option=torture:filename=... \n " ) ) ;
return false ;
}
2007-09-29 18:00:19 +00:00
num_locks = lp_parm_int ( global_loadparm , NULL , " torture " , " num_locks " , - 1 ) ;
2007-08-29 05:45:24 +00:00
if ( num_locks = = - 1 ) {
DEBUG ( 0 , ( " You must specify num_locks using --option=torture:num_locks=... \n " ) ) ;
return false ;
}
2007-09-29 18:00:19 +00:00
do_reads = lp_parm_bool ( global_loadparm , NULL , " torture " , " read " , false ) ;
do_writes = lp_parm_bool ( global_loadparm , NULL , " torture " , " write " , false ) ;
lock_timeout = lp_parm_int ( global_loadparm , NULL , " torture " , " lock_timeout " , 100000 ) ;
2007-08-29 05:45:24 +00:00
2007-08-29 06:58:25 +00:00
if ( ! torture_open_connection ( & cli , 0 ) ) {
DEBUG ( 0 , ( " Could not open connection \n " ) ) ;
return false ;
2007-08-29 05:45:24 +00:00
}
2007-08-29 06:58:25 +00:00
fd = smbcli_open ( cli - > tree , fn , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fd = = - 1 ) {
2007-08-29 05:45:24 +00:00
printf ( " Failed to open %s \n " , fn ) ;
exit ( 1 ) ;
}
2007-08-29 06:58:25 +00:00
write_byte ( cli , fd , 0 , num_locks ) ;
lock_byte ( cli , fd , 0 , lock_timeout ) ;
2007-08-29 05:45:24 +00:00
2007-08-29 06:58:25 +00:00
start_timer ( ) ;
val = talloc_zero_array ( mem_ctx , uint8_t , num_locks ) ;
i = 0 ;
count = 0 ;
loops = 0 ;
while ( 1 ) {
lock_byte ( cli , fd , ( i + 1 ) % num_locks , lock_timeout ) ;
2007-08-29 05:45:24 +00:00
2007-08-29 06:58:25 +00:00
if ( do_reads ) {
uint8_t c ;
read_byte ( cli , fd , & c , i ) ;
incr = c - val [ i ] ;
val [ i ] = c ;
2007-08-29 05:45:24 +00:00
}
2007-08-29 06:58:25 +00:00
if ( do_writes ) {
uint8_t c = val [ i ] + 1 ;
write_byte ( cli , fd , c , i ) ;
}
unlock_byte ( cli , fd , i ) ;
i = ( i + 1 ) % num_locks ;
count + + ;
if ( loops > num_locks & & incr ! = last_incr ) {
last_incr = incr ;
printf ( " data increment = %u \n " , incr ) ;
fflush ( stdout ) ;
}
if ( end_timer ( ) > 1.0 ) {
printf ( " %8u locks/sec \r " ,
( unsigned ) ( 2 * count / end_timer ( ) ) ) ;
fflush ( stdout ) ;
start_timer ( ) ;
count = 0 ;
}
loops + + ;
}
2007-08-29 05:45:24 +00:00
talloc_free ( mem_ctx ) ;
return true ;
}
2007-08-29 06:58:25 +00:00