0001-01-01 02:30:17 +02:30
/*
0001-01-01 02:30:17 +02:30
Unix SMB / CIFS implementation .
0001-01-01 02:30:17 +02:30
randomised byte range lock tester
0001-01-01 02:30:17 +02:30
Copyright ( C ) Andrew Tridgell 1999
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 2 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 , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# define NO_SYSLOG
# include "includes.h"
static fstring password ;
static fstring username ;
static int got_pass ;
static int numops = 1000 ;
0001-01-01 02:30:17 +02:30
static BOOL showall ;
0001-01-01 02:30:17 +02:30
static BOOL analyze ;
0001-01-01 02:30:17 +02:30
static BOOL hide_unlock_fails ;
0001-01-01 02:30:17 +02:30
static BOOL use_oplocks ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
# define FILENAME "\\locktest.dat"
0001-01-01 02:30:17 +02:30
# define LOCKRANGE 100
0001-01-01 02:30:17 +02:30
# define LOCKBASE 0
0001-01-01 02:30:17 +02:30
# define MINLENGTH 0
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
# define ZERO_ZERO 0
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/*
# define LOCKBASE (0x40000000 - 50)
*/
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
# define READ_PCT 50
0001-01-01 02:30:17 +02:30
# define LOCK_PCT 45
# define UNLOCK_PCT 70
0001-01-01 02:30:17 +02:30
# define RANGE_MULTIPLE 1
0001-01-01 02:30:17 +02:30
# define NSERVERS 2
0001-01-01 02:30:17 +02:30
# define NCONNECTIONS 2
# define NFILES 2
0001-01-01 02:30:17 +02:30
# define LOCK_TIMEOUT 0
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
# define NASTY_POSIX_LOCK_HACK 0
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
enum lock_op { OP_LOCK , OP_UNLOCK , OP_REOPEN } ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
struct record {
0001-01-01 02:30:17 +02:30
enum lock_op lock_op ;
0001-01-01 02:30:17 +02:30
enum brl_type lock_type ;
0001-01-01 02:30:17 +02:30
char conn , f ;
0001-01-01 02:30:17 +02:30
SMB_BIG_UINT start , len ;
0001-01-01 02:30:17 +02:30
char needed ;
0001-01-01 02:30:17 +02:30
} ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
# define PRESETS 0
# if PRESETS
0001-01-01 02:30:17 +02:30
static struct record preset [ ] = {
0001-01-01 02:30:17 +02:30
{ OP_LOCK , WRITE_LOCK , 0 , 0 , 2 , 0 , 1 } ,
{ OP_LOCK , WRITE_LOCK , 0 , 0 , 0 , 0 , 1 } ,
{ OP_LOCK , WRITE_LOCK , 0 , 0 , 3 , 0 , 1 } ,
{ OP_UNLOCK , 0 , 0 , 0 , 2 , 0 , 1 } ,
{ OP_REOPEN , 0 , 0 , 0 , 0 , 0 , 1 } ,
{ OP_LOCK , READ_LOCK , 0 , 0 , 2 , 0 , 1 } ,
{ OP_LOCK , READ_LOCK , 0 , 0 , 1 , 1 , 1 } ,
{ OP_LOCK , WRITE_LOCK , 0 , 0 , 0 , 0 , 1 } ,
{ OP_REOPEN , 0 , 0 , 0 , 0 , 0 , 1 } ,
{ OP_LOCK , READ_LOCK , 0 , 0 , 2 , 0 , 1 } ,
{ OP_LOCK , WRITE_LOCK , 0 , 0 , 3 , 1 , 1 } ,
{ OP_LOCK , WRITE_LOCK , 0 , 0 , 0 , 0 , 1 } ,
{ OP_REOPEN , 0 , 0 , 0 , 0 , 0 , 1 } ,
{ OP_LOCK , READ_LOCK , 0 , 0 , 2 , 0 , 1 } ,
{ OP_LOCK , WRITE_LOCK , 0 , 0 , 1 , 1 , 1 } ,
{ OP_LOCK , WRITE_LOCK , 0 , 0 , 0 , 0 , 1 } ,
{ OP_REOPEN , 0 , 0 , 0 , 0 , 0 , 1 } ,
{ OP_LOCK , WRITE_LOCK , 0 , 0 , 2 , 0 , 1 } ,
{ OP_LOCK , READ_LOCK , 0 , 0 , 1 , 1 , 1 } ,
{ OP_LOCK , WRITE_LOCK , 0 , 0 , 0 , 0 , 1 } ,
{ OP_REOPEN , 0 , 0 , 0 , 0 , 0 , 1 } ,
{ OP_LOCK , WRITE_LOCK , 0 , 0 , 2 , 0 , 1 } ,
{ OP_LOCK , READ_LOCK , 0 , 0 , 3 , 1 , 1 } ,
{ OP_LOCK , WRITE_LOCK , 0 , 0 , 0 , 0 , 1 } ,
{ OP_REOPEN , 0 , 0 , 0 , 0 , 0 , 1 } ,
0001-01-01 02:30:17 +02:30
} ;
0001-01-01 02:30:17 +02:30
# endif
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static struct record * recorded ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static void print_brl ( SMB_DEV_T dev , SMB_INO_T ino , int pid ,
enum brl_type lock_type ,
br_off start , br_off size )
{
0001-01-01 02:30:17 +02:30
# if NASTY_POSIX_LOCK_HACK
{
pstring cmd ;
static SMB_INO_T lastino ;
if ( lastino ! = ino ) {
slprintf ( cmd , sizeof ( cmd ) ,
0001-01-01 02:30:17 +02:30
" egrep POSIX.*%u /proc/locks " , ( int ) ino ) ;
0001-01-01 02:30:17 +02:30
system ( cmd ) ;
}
lastino = ino ;
}
# endif
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
printf ( " %6d %05x:%05x %s %.0f:%.0f(%.0f) \n " ,
0001-01-01 02:30:17 +02:30
( int ) pid , ( int ) dev , ( int ) ino ,
lock_type = = READ_LOCK ? " R " : " W " ,
0001-01-01 02:30:17 +02:30
( double ) start , ( double ) start + size - 1 , ( double ) size ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
static void show_locks ( void )
{
brl_forall ( print_brl ) ;
0001-01-01 02:30:17 +02:30
/* system("cat /proc/locks"); */
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/*****************************************************
return a connection to a server
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
struct cli_state * connect_one ( char * share )
{
struct cli_state * c ;
struct nmb_name called , calling ;
char * server_n ;
fstring server ;
struct in_addr ip ;
0001-01-01 02:30:17 +02:30
fstring myname ;
static int count ;
0001-01-01 02:30:17 +02:30
fstrcpy ( server , share + 2 ) ;
0001-01-01 02:30:17 +02:30
share = strchr_m ( server , ' \\ ' ) ;
0001-01-01 02:30:17 +02:30
if ( ! share ) return NULL ;
* share = 0 ;
share + + ;
server_n = server ;
0001-01-01 02:30:17 +02:30
zero_ip ( & ip ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
slprintf ( myname , sizeof ( myname ) , " lock-%u-%u " , getpid ( ) , count + + ) ;
0001-01-01 02:30:17 +02:30
make_nmb_name ( & calling , myname , 0x0 ) ;
0001-01-01 02:30:17 +02:30
make_nmb_name ( & called , server , 0x20 ) ;
again :
0001-01-01 02:30:17 +02:30
zero_ip ( & ip ) ;
0001-01-01 02:30:17 +02:30
/* have to open a new connection */
0001-01-01 02:30:17 +02:30
if ( ! ( c = cli_initialise ( NULL ) ) | | ! cli_connect ( c , server_n , & ip ) ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " Connection to %s failed \n " , server_n ) ) ;
return NULL ;
}
if ( ! cli_session_request ( c , & calling , & called ) ) {
DEBUG ( 0 , ( " session request to %s failed \n " , called . name ) ) ;
cli_shutdown ( c ) ;
if ( strcmp ( called . name , " *SMBSERVER " ) ) {
make_nmb_name ( & called , " *SMBSERVER " , 0x20 ) ;
goto again ;
}
return NULL ;
}
DEBUG ( 4 , ( " session request ok \n " ) ) ;
if ( ! cli_negprot ( c ) ) {
DEBUG ( 0 , ( " protocol negotiation failed \n " ) ) ;
cli_shutdown ( c ) ;
return NULL ;
}
if ( ! got_pass ) {
char * pass = getpass ( " Password: " ) ;
if ( pass ) {
pstrcpy ( password , pass ) ;
}
}
if ( ! cli_session_setup ( c , username ,
password , strlen ( password ) ,
password , strlen ( password ) ,
0001-01-01 02:30:17 +02:30
lp_workgroup ( ) ) ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " session setup failed: %s \n " , cli_errstr ( c ) ) ) ;
return NULL ;
}
/*
* These next two lines are needed to emulate
* old client behaviour for people who have
* scripts based on client output .
* QUESTION ? Do we want to have a ' client compatibility
* mode to turn these on / off ? JRA .
*/
if ( * c - > server_domain | | * c - > server_os | | * c - > server_type )
DEBUG ( 1 , ( " Domain=[%s] OS=[%s] Server=[%s] \n " ,
c - > server_domain , c - > server_os , c - > server_type ) ) ;
DEBUG ( 4 , ( " session setup ok \n " ) ) ;
if ( ! cli_send_tconX ( c , share , " ????? " ,
password , strlen ( password ) + 1 ) ) {
DEBUG ( 0 , ( " tree connect failed: %s \n " , cli_errstr ( c ) ) ) ;
cli_shutdown ( c ) ;
return NULL ;
}
DEBUG ( 4 , ( " tconx ok \n " ) ) ;
0001-01-01 02:30:17 +02:30
c - > use_oplocks = use_oplocks ;
0001-01-01 02:30:17 +02:30
return c ;
}
0001-01-01 02:30:17 +02:30
static void reconnect ( struct cli_state * cli [ NSERVERS ] [ NCONNECTIONS ] , int fnum [ NSERVERS ] [ NCONNECTIONS ] [ NFILES ] ,
char * share [ NSERVERS ] )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
int server , conn , f ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
for ( server = 0 ; server < NSERVERS ; server + + )
0001-01-01 02:30:17 +02:30
for ( conn = 0 ; conn < NCONNECTIONS ; conn + + ) {
0001-01-01 02:30:17 +02:30
if ( cli [ server ] [ conn ] ) {
0001-01-01 02:30:17 +02:30
for ( f = 0 ; f < NFILES ; f + + ) {
0001-01-01 02:30:17 +02:30
cli_close ( cli [ server ] [ conn ] , fnum [ server ] [ conn ] [ f ] ) ;
}
cli_ulogoff ( cli [ server ] [ conn ] ) ;
0001-01-01 02:30:17 +02:30
cli_shutdown ( cli [ server ] [ conn ] ) ;
}
cli [ server ] [ conn ] = connect_one ( share [ server ] ) ;
if ( ! cli [ server ] [ conn ] ) {
DEBUG ( 0 , ( " Failed to connect to %s \n " , share [ server ] ) ) ;
exit ( 1 ) ;
}
}
}
0001-01-01 02:30:17 +02:30
static BOOL test_one ( struct cli_state * cli [ NSERVERS ] [ NCONNECTIONS ] ,
int fnum [ NSERVERS ] [ NCONNECTIONS ] [ NFILES ] ,
0001-01-01 02:30:17 +02:30
struct record * rec )
{
0001-01-01 02:30:17 +02:30
unsigned conn = rec - > conn ;
unsigned f = rec - > f ;
0001-01-01 02:30:17 +02:30
SMB_BIG_UINT start = rec - > start ;
SMB_BIG_UINT len = rec - > len ;
0001-01-01 02:30:17 +02:30
enum brl_type op = rec - > lock_type ;
0001-01-01 02:30:17 +02:30
int server ;
BOOL ret [ NSERVERS ] ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
switch ( rec - > lock_op ) {
case OP_LOCK :
0001-01-01 02:30:17 +02:30
/* set a lock */
0001-01-01 02:30:17 +02:30
for ( server = 0 ; server < NSERVERS ; server + + ) {
0001-01-01 02:30:17 +02:30
ret [ server ] = cli_lock64 ( cli [ server ] [ conn ] ,
fnum [ server ] [ conn ] [ f ] ,
start , len , LOCK_TIMEOUT , op ) ;
0001-01-01 02:30:17 +02:30
}
if ( showall | | ret [ 0 ] ! = ret [ 1 ] ) {
0001-01-01 02:30:17 +02:30
printf ( " lock conn=%u f=%u range=%.0f(%.0f) op=%s -> %u:%u \n " ,
0001-01-01 02:30:17 +02:30
conn , f ,
0001-01-01 02:30:17 +02:30
( double ) start , ( double ) len ,
0001-01-01 02:30:17 +02:30
op = = READ_LOCK ? " READ_LOCK " : " WRITE_LOCK " ,
0001-01-01 02:30:17 +02:30
ret [ 0 ] , ret [ 1 ] ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
if ( showall | | ret [ 0 ] ! = ret [ 1 ] ) show_locks ( ) ;
if ( ret [ 0 ] ! = ret [ 1 ] ) return False ;
0001-01-01 02:30:17 +02:30
break ;
case OP_UNLOCK :
0001-01-01 02:30:17 +02:30
/* unset a lock */
0001-01-01 02:30:17 +02:30
for ( server = 0 ; server < NSERVERS ; server + + ) {
0001-01-01 02:30:17 +02:30
ret [ server ] = cli_unlock64 ( cli [ server ] [ conn ] ,
fnum [ server ] [ conn ] [ f ] ,
start , len ) ;
0001-01-01 02:30:17 +02:30
}
if ( showall | | ( ! hide_unlock_fails & & ( ret [ 0 ] ! = ret [ 1 ] ) ) ) {
0001-01-01 02:30:17 +02:30
printf ( " unlock conn=%u f=%u range=%.0f(%.0f) -> %u:%u \n " ,
0001-01-01 02:30:17 +02:30
conn , f ,
0001-01-01 02:30:17 +02:30
( double ) start , ( double ) len ,
0001-01-01 02:30:17 +02:30
ret [ 0 ] , ret [ 1 ] ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
if ( showall | | ret [ 0 ] ! = ret [ 1 ] ) show_locks ( ) ;
if ( ! hide_unlock_fails & & ret [ 0 ] ! = ret [ 1 ] ) return False ;
0001-01-01 02:30:17 +02:30
break ;
case OP_REOPEN :
0001-01-01 02:30:17 +02:30
/* reopen the file */
0001-01-01 02:30:17 +02:30
for ( server = 0 ; server < NSERVERS ; server + + ) {
cli_close ( cli [ server ] [ conn ] , fnum [ server ] [ conn ] [ f ] ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
for ( server = 0 ; server < NSERVERS ; server + + ) {
fnum [ server ] [ conn ] [ f ] = cli_open ( cli [ server ] [ conn ] , FILENAME ,
O_RDWR | O_CREAT ,
DENY_NONE ) ;
if ( fnum [ server ] [ conn ] [ f ] = = - 1 ) {
printf ( " failed to reopen on share%d \n " , server ) ;
return False ;
}
0001-01-01 02:30:17 +02:30
}
if ( showall ) {
0001-01-01 02:30:17 +02:30
printf ( " reopen conn=%u f=%u \n " ,
0001-01-01 02:30:17 +02:30
conn , f ) ;
0001-01-01 02:30:17 +02:30
show_locks ( ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
break ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
return True ;
}
0001-01-01 02:30:17 +02:30
static void close_files ( struct cli_state * cli [ NSERVERS ] [ NCONNECTIONS ] ,
int fnum [ NSERVERS ] [ NCONNECTIONS ] [ NFILES ] )
0001-01-01 02:30:17 +02:30
{
int server , conn , f ;
0001-01-01 02:30:17 +02:30
for ( server = 0 ; server < NSERVERS ; server + + )
0001-01-01 02:30:17 +02:30
for ( conn = 0 ; conn < NCONNECTIONS ; conn + + )
for ( f = 0 ; f < NFILES ; f + + ) {
0001-01-01 02:30:17 +02:30
if ( fnum [ server ] [ conn ] [ f ] ! = - 1 ) {
cli_close ( cli [ server ] [ conn ] , fnum [ server ] [ conn ] [ f ] ) ;
0001-01-01 02:30:17 +02:30
fnum [ server ] [ conn ] [ f ] = - 1 ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
for ( server = 0 ; server < NSERVERS ; server + + ) {
cli_unlink ( cli [ server ] [ 0 ] , FILENAME ) ;
}
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
static void open_files ( struct cli_state * cli [ NSERVERS ] [ NCONNECTIONS ] ,
int fnum [ NSERVERS ] [ NCONNECTIONS ] [ NFILES ] )
0001-01-01 02:30:17 +02:30
{
int server , conn , f ;
0001-01-01 02:30:17 +02:30
for ( server = 0 ; server < NSERVERS ; server + + )
0001-01-01 02:30:17 +02:30
for ( conn = 0 ; conn < NCONNECTIONS ; conn + + )
for ( f = 0 ; f < NFILES ; f + + ) {
0001-01-01 02:30:17 +02:30
fnum [ server ] [ conn ] [ f ] = cli_open ( cli [ server ] [ conn ] , FILENAME ,
O_RDWR | O_CREAT ,
DENY_NONE ) ;
if ( fnum [ server ] [ conn ] [ f ] = = - 1 ) {
0001-01-01 02:30:17 +02:30
fprintf ( stderr , " Failed to open fnum[%u][%u][%u] \n " ,
0001-01-01 02:30:17 +02:30
server , conn , f ) ;
exit ( 1 ) ;
}
}
}
0001-01-01 02:30:17 +02:30
static int retest ( struct cli_state * cli [ NSERVERS ] [ NCONNECTIONS ] ,
int fnum [ NSERVERS ] [ NCONNECTIONS ] [ NFILES ] ,
0001-01-01 02:30:17 +02:30
int n )
{
int i ;
0001-01-01 02:30:17 +02:30
printf ( " testing %u ... \n " , n ) ;
0001-01-01 02:30:17 +02:30
for ( i = 0 ; i < n ; i + + ) {
0001-01-01 02:30:17 +02:30
if ( i & & i % 100 = = 0 ) {
0001-01-01 02:30:17 +02:30
printf ( " %u \n " , i ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
if ( recorded [ i ] . needed & &
! test_one ( cli , fnum , & recorded [ i ] ) ) return i ;
0001-01-01 02:30:17 +02:30
}
return n ;
}
/* each server has two connections open to it. Each connection has two file
descriptors open on the file - 8 file descriptors in total
we then do random locking ops in tamdem on the 4 fnums from each
server and ensure that the results match
*/
0001-01-01 02:30:17 +02:30
static void test_locks ( char * share [ NSERVERS ] )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
struct cli_state * cli [ NSERVERS ] [ NCONNECTIONS ] ;
int fnum [ NSERVERS ] [ NCONNECTIONS ] [ NFILES ] ;
0001-01-01 02:30:17 +02:30
int n , i , n1 , skip , r1 , r2 ;
0001-01-01 02:30:17 +02:30
ZERO_STRUCT ( fnum ) ;
ZERO_STRUCT ( cli ) ;
recorded = ( struct record * ) malloc ( sizeof ( * recorded ) * numops ) ;
for ( n = 0 ; n < numops ; n + + ) {
0001-01-01 02:30:17 +02:30
# if PRESETS
0001-01-01 02:30:17 +02:30
if ( n < sizeof ( preset ) / sizeof ( preset [ 0 ] ) ) {
recorded [ n ] = preset [ n ] ;
} else {
0001-01-01 02:30:17 +02:30
# endif
0001-01-01 02:30:17 +02:30
recorded [ n ] . conn = random ( ) % NCONNECTIONS ;
recorded [ n ] . f = random ( ) % NFILES ;
0001-01-01 02:30:17 +02:30
recorded [ n ] . start = LOCKBASE + ( ( unsigned ) random ( ) % ( LOCKRANGE - 1 ) ) ;
0001-01-01 02:30:17 +02:30
recorded [ n ] . len = MINLENGTH +
0001-01-01 02:30:17 +02:30
random ( ) % ( LOCKRANGE - ( recorded [ n ] . start - LOCKBASE ) ) ;
0001-01-01 02:30:17 +02:30
recorded [ n ] . start * = RANGE_MULTIPLE ;
recorded [ n ] . len * = RANGE_MULTIPLE ;
0001-01-01 02:30:17 +02:30
r1 = random ( ) % 100 ;
r2 = random ( ) % 100 ;
if ( r1 < READ_PCT ) {
recorded [ n ] . lock_type = READ_LOCK ;
} else {
recorded [ n ] . lock_type = WRITE_LOCK ;
}
if ( r2 < LOCK_PCT ) {
recorded [ n ] . lock_op = OP_LOCK ;
} else if ( r2 < UNLOCK_PCT ) {
recorded [ n ] . lock_op = OP_UNLOCK ;
} else {
recorded [ n ] . lock_op = OP_REOPEN ;
}
0001-01-01 02:30:17 +02:30
recorded [ n ] . needed = True ;
0001-01-01 02:30:17 +02:30
# if !ZERO_ZERO
if ( recorded [ n ] . start = = 0 & &
recorded [ n ] . len = = 0 ) {
recorded [ n ] . len = 1 ;
}
# endif
0001-01-01 02:30:17 +02:30
# if PRESETS
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
# endif
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
reconnect ( cli , fnum , share ) ;
0001-01-01 02:30:17 +02:30
open_files ( cli , fnum ) ;
n = retest ( cli , fnum , numops ) ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( n = = numops | | ! analyze ) return ;
0001-01-01 02:30:17 +02:30
n + + ;
0001-01-01 02:30:17 +02:30
skip = n / 2 ;
0001-01-01 02:30:17 +02:30
while ( 1 ) {
n1 = n ;
0001-01-01 02:30:17 +02:30
close_files ( cli , fnum ) ;
0001-01-01 02:30:17 +02:30
reconnect ( cli , fnum , share ) ;
0001-01-01 02:30:17 +02:30
open_files ( cli , fnum ) ;
0001-01-01 02:30:17 +02:30
for ( i = 0 ; i < n - skip ; i + = skip ) {
0001-01-01 02:30:17 +02:30
int m , j ;
0001-01-01 02:30:17 +02:30
printf ( " excluding %d-%d \n " , i , i + skip - 1 ) ;
0001-01-01 02:30:17 +02:30
for ( j = i ; j < i + skip ; j + + ) {
recorded [ j ] . needed = False ;
}
0001-01-01 02:30:17 +02:30
close_files ( cli , fnum ) ;
open_files ( cli , fnum ) ;
0001-01-01 02:30:17 +02:30
m = retest ( cli , fnum , n ) ;
if ( m = = n ) {
0001-01-01 02:30:17 +02:30
for ( j = i ; j < i + skip ; j + + ) {
recorded [ j ] . needed = True ;
}
0001-01-01 02:30:17 +02:30
} else {
0001-01-01 02:30:17 +02:30
if ( i + ( skip - 1 ) < m ) {
memmove ( & recorded [ i ] , & recorded [ i + skip ] ,
( m - ( i + skip - 1 ) ) * sizeof ( recorded [ 0 ] ) ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
n = m - ( skip - 1 ) ;
0001-01-01 02:30:17 +02:30
i - - ;
}
}
0001-01-01 02:30:17 +02:30
if ( skip > 1 ) {
skip = skip / 2 ;
printf ( " skip=%d \n " , skip ) ;
continue ;
}
0001-01-01 02:30:17 +02:30
if ( n1 = = n ) break ;
}
0001-01-01 02:30:17 +02:30
close_files ( cli , fnum ) ;
0001-01-01 02:30:17 +02:30
reconnect ( cli , fnum , share ) ;
0001-01-01 02:30:17 +02:30
open_files ( cli , fnum ) ;
showall = True ;
n1 = retest ( cli , fnum , n ) ;
if ( n1 ! = n - 1 ) {
0001-01-01 02:30:17 +02:30
printf ( " ERROR - inconsistent result (%u %u) \n " , n1 , n ) ;
0001-01-01 02:30:17 +02:30
}
close_files ( cli , fnum ) ;
0001-01-01 02:30:17 +02:30
for ( i = 0 ; i < n ; i + + ) {
0001-01-01 02:30:17 +02:30
printf ( " {%d, %d, %u, %u, %.0f, %.0f, %u}, \n " ,
recorded [ i ] . lock_op ,
recorded [ i ] . lock_type ,
0001-01-01 02:30:17 +02:30
recorded [ i ] . conn ,
recorded [ i ] . f ,
0001-01-01 02:30:17 +02:30
( double ) recorded [ i ] . start ,
( double ) recorded [ i ] . len ,
0001-01-01 02:30:17 +02:30
recorded [ i ] . needed ) ;
}
}
0001-01-01 02:30:17 +02:30
static void usage ( void )
{
printf (
" Usage: \n \
locktest / / server1 / share1 / / server2 / share2 [ options . . ] \ n \
options : \ n \
- U user % % pass \ n \
- s seed \ n \
0001-01-01 02:30:17 +02:30
- o numops \ n \
0001-01-01 02:30:17 +02:30
- u hide unlock fails \ n \
0001-01-01 02:30:17 +02:30
- a ( show all ops ) \ n \
0001-01-01 02:30:17 +02:30
- A analyse for minimal ops \ n \
0001-01-01 02:30:17 +02:30
- O use oplocks \ n \
0001-01-01 02:30:17 +02:30
" );
}
/****************************************************************************
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int main ( int argc , char * argv [ ] )
{
0001-01-01 02:30:17 +02:30
char * share [ NSERVERS ] ;
0001-01-01 02:30:17 +02:30
extern char * optarg ;
extern int optind ;
int opt ;
char * p ;
0001-01-01 02:30:17 +02:30
int seed , server ;
0001-01-01 02:30:17 +02:30
setlinebuf ( stdout ) ;
0001-01-01 02:30:17 +02:30
dbf = x_stderr ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
if ( argc < 3 | | argv [ 1 ] [ 0 ] = = ' - ' ) {
0001-01-01 02:30:17 +02:30
usage ( ) ;
exit ( 1 ) ;
}
setup_logging ( argv [ 0 ] , True ) ;
0001-01-01 02:30:17 +02:30
for ( server = 0 ; server < NSERVERS ; server + + ) {
share [ server ] = argv [ 1 + server ] ;
all_string_sub ( share [ server ] , " / " , " \\ " , 0 ) ;
}
argc - = NSERVERS ;
argv + = NSERVERS ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
lp_load ( dyn_CONFIGFILE , True , False , False ) ;
0001-01-01 02:30:17 +02:30
load_interfaces ( ) ;
if ( getenv ( " USER " ) ) {
pstrcpy ( username , getenv ( " USER " ) ) ;
}
seed = time ( NULL ) ;
0001-01-01 02:30:17 +02:30
while ( ( opt = getopt ( argc , argv , " U:s:ho:aAW:O " ) ) ! = EOF ) {
0001-01-01 02:30:17 +02:30
switch ( opt ) {
case ' U ' :
pstrcpy ( username , optarg ) ;
0001-01-01 02:30:17 +02:30
p = strchr_m ( username , ' % ' ) ;
0001-01-01 02:30:17 +02:30
if ( p ) {
* p = 0 ;
pstrcpy ( password , p + 1 ) ;
got_pass = 1 ;
}
break ;
case ' s ' :
seed = atoi ( optarg ) ;
break ;
0001-01-01 02:30:17 +02:30
case ' u ' :
hide_unlock_fails = True ;
break ;
0001-01-01 02:30:17 +02:30
case ' o ' :
numops = atoi ( optarg ) ;
break ;
0001-01-01 02:30:17 +02:30
case ' O ' :
use_oplocks = True ;
break ;
0001-01-01 02:30:17 +02:30
case ' a ' :
showall = True ;
break ;
0001-01-01 02:30:17 +02:30
case ' A ' :
analyze = True ;
break ;
0001-01-01 02:30:17 +02:30
case ' h ' :
usage ( ) ;
exit ( 1 ) ;
default :
printf ( " Unknown option %c (%d) \n " , ( char ) opt , opt ) ;
exit ( 1 ) ;
}
}
argc - = optind ;
argv + = optind ;
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " seed=%u \n " , seed ) ) ;
0001-01-01 02:30:17 +02:30
srandom ( seed ) ;
0001-01-01 02:30:17 +02:30
test_locks ( share ) ;
0001-01-01 02:30:17 +02:30
return ( 0 ) ;
}