2024-05-31 22:28:50 +03:00
/*
2007-08-29 09:45:24 +04:00
Unix SMB / CIFS implementation .
ping pong test
2007-08-29 10:58:25 +04:00
Copyright ( C ) Ronnie Sahlberg 2007
Significantly based on and borrowed from lockbench . c by
Copyright ( C ) Andrew Tridgell 2006
2024-05-31 22:28:50 +03:00
2007-08-29 10:58:25 +04:00
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 .
2024-05-31 22:28:50 +03:00
2007-08-29 10:58:25 +04:00
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 .
2024-05-31 22:28:50 +03:00
2007-08-29 10:58:25 +04:00
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 09:45:24 +04: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-07 02:28:14 +04:00
- - option = torture : read = true
2007-08-29 09:45:24 +04:00
writing to the file can be enabled with
2007-10-07 02:28:14 +04:00
- - option = torture : write = true
2007-08-29 09:45:24 +04:00
*/
# include "includes.h"
# include "system/time.h"
# include "system/filesys.h"
# include "libcli/libcli.h"
# include "torture/util.h"
2011-03-19 02:42:42 +03:00
# include "torture/raw/proto.h"
2007-08-29 09:45:24 +04:00
2007-09-08 20:46:30 +04:00
static void lock_byte ( struct smbcli_state * cli , int fd , int offset , int lock_timeout )
2007-08-29 09:45:24 +04:00
{
union smb_lock io ;
struct smb_lock_entry lock ;
2007-08-29 10:58:25 +04:00
NTSTATUS status ;
2007-08-29 09:45:24 +04:00
2007-08-29 10:58:25 +04:00
try_again :
ZERO_STRUCT ( lock ) ;
io . lockx . in . ulock_cnt = 0 ;
io . lockx . in . lock_cnt = 1 ;
2007-08-29 09:45:24 +04:00
2007-08-29 10:58:25 +04: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 ) ;
2015-07-27 00:02:57 +03:00
/* If we don't use timeouts and we got file lock conflict
2007-08-29 10:58:25 +04:00
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 09:45:24 +04:00
}
}
2007-08-29 10:58:25 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Lock failed \n " ) ) ;
exit ( 1 ) ;
2007-08-29 09:45:24 +04:00
}
2007-08-29 10:58:25 +04:00
}
2007-08-29 09:45:24 +04:00
2007-09-08 20:46:30 +04:00
static void unlock_byte ( struct smbcli_state * cli , int fd , int offset )
2007-08-29 10:58:25 +04:00
{
union smb_lock io ;
struct smb_lock_entry lock ;
NTSTATUS status ;
2007-08-29 09:45:24 +04:00
2007-08-29 10:58:25 +04: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 09:45:24 +04:00
io . lockx . level = RAW_LOCK_LOCKX ;
io . lockx . in . mode = LOCKING_ANDX_LARGE_FILES ;
2007-08-29 10:58:25 +04:00
io . lockx . in . timeout = 100000 ;
2007-08-29 09:45:24 +04:00
io . lockx . in . locks = & lock ;
2007-08-29 10:58:25 +04:00
io . lockx . in . file . fnum = fd ;
2007-08-29 09:45:24 +04:00
2007-08-29 10:58:25 +04:00
status = smb_raw_lock ( cli - > tree , & io ) ;
2007-08-29 09:45:24 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-29 10:58:25 +04:00
DEBUG ( 0 , ( " Unlock failed \n " ) ) ;
2007-08-29 09:45:24 +04:00
exit ( 1 ) ;
}
}
2007-09-08 20:46:30 +04:00
static void write_byte ( struct smbcli_state * cli , int fd , uint8_t c , int offset )
2007-08-29 09:45:24 +04:00
{
union smb_write io ;
2007-08-29 10:58:25 +04:00
NTSTATUS status ;
2007-08-29 09:45:24 +04:00
io . generic . level = RAW_WRITE_WRITEX ;
2007-08-29 10:58:25 +04:00
io . writex . in . file . fnum = fd ;
io . writex . in . offset = offset ;
2007-08-29 09:45:24 +04:00
io . writex . in . wmode = 0 ;
io . writex . in . remaining = 0 ;
io . writex . in . count = 1 ;
2007-08-29 10:58:25 +04:00
io . writex . in . data = & c ;
2007-08-29 09:45:24 +04:00
2007-08-29 10:58:25 +04:00
status = smb_raw_write ( cli - > tree , & io ) ;
2007-08-29 09:45:24 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-29 10:58:25 +04:00
printf ( " write failed \n " ) ;
2007-08-29 09:45:24 +04:00
exit ( 1 ) ;
}
2024-05-31 22:28:50 +03:00
}
2007-08-29 09:45:24 +04:00
2007-09-08 20:46:30 +04:00
static void read_byte ( struct smbcli_state * cli , int fd , uint8_t * c , int offset )
2007-08-29 09:45:24 +04:00
{
union smb_read io ;
2007-08-29 10:58:25 +04:00
NTSTATUS status ;
2007-08-29 09:45:24 +04:00
io . generic . level = RAW_READ_READX ;
2007-08-29 10:58:25 +04:00
io . readx . in . file . fnum = fd ;
2007-08-29 09:45:24 +04:00
io . readx . in . mincnt = 1 ;
io . readx . in . maxcnt = 1 ;
2007-08-29 10:58:25 +04:00
io . readx . in . offset = offset ;
2007-08-29 09:45:24 +04:00
io . readx . in . remaining = 0 ;
2007-10-07 02:28:14 +04:00
io . readx . in . read_for_execute = false ;
2007-08-29 10:58:25 +04:00
io . readx . out . data = c ;
2007-08-29 09:45:24 +04:00
2007-08-29 10:58:25 +04:00
status = smb_raw_read ( cli - > tree , & io ) ;
2007-08-29 09:45:24 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-29 10:58:25 +04:00
printf ( " read failed \n " ) ;
exit ( 1 ) ;
2007-08-29 09:45:24 +04:00
}
2024-05-31 22:28:50 +03:00
}
2007-08-29 09:45:24 +04:00
2024-05-31 22:28:50 +03:00
/*
2007-08-29 09:45:24 +04:00
ping pong
*/
2007-09-08 20:46:30 +04:00
bool torture_ping_pong ( struct torture_context * torture )
2007-08-29 09:45:24 +04:00
{
const char * fn ;
2007-08-29 10:58:25 +04:00
int num_locks ;
2007-08-29 09:45:24 +04:00
TALLOC_CTX * mem_ctx = talloc_new ( torture ) ;
2007-10-07 02:28:14 +04:00
static bool do_reads ;
static bool do_writes ;
2007-08-29 10:58:25 +04:00
int lock_timeout ;
int fd ;
2007-08-29 09:45:24 +04:00
struct smbcli_state * cli ;
2007-08-29 10:58:25 +04:00
int i ;
uint8_t incr = 0 , last_incr = 0 ;
uint8_t * val ;
int count , loops ;
2009-11-24 12:18:37 +03:00
struct timeval start ;
2007-08-29 09:45:24 +04:00
2007-12-03 02:28:22 +03:00
fn = torture_setting_string ( torture , " filename " , NULL ) ;
2007-08-29 09:45:24 +04:00
if ( fn = = NULL ) {
DEBUG ( 0 , ( " You must specify the filename using --option=torture:filename=... \n " ) ) ;
return false ;
}
2007-12-03 02:28:22 +03:00
num_locks = torture_setting_int ( torture , " num_locks " , - 1 ) ;
2007-08-29 09:45:24 +04:00
if ( num_locks = = - 1 ) {
DEBUG ( 0 , ( " You must specify num_locks using --option=torture:num_locks=... \n " ) ) ;
return false ;
}
2007-12-03 02:28:22 +03:00
do_reads = torture_setting_bool ( torture , " read " , false ) ;
do_writes = torture_setting_bool ( torture , " write " , false ) ;
lock_timeout = torture_setting_int ( torture , " lock_timeout " , 100000 ) ;
2007-08-29 09:45:24 +04:00
2007-12-03 17:53:07 +03:00
if ( ! torture_open_connection ( & cli , torture , 0 ) ) {
2007-08-29 10:58:25 +04:00
DEBUG ( 0 , ( " Could not open connection \n " ) ) ;
return false ;
2007-08-29 09:45:24 +04:00
}
2007-08-29 10:58:25 +04:00
fd = smbcli_open ( cli - > tree , fn , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fd = = - 1 ) {
2007-08-29 09:45:24 +04:00
printf ( " Failed to open %s \n " , fn ) ;
exit ( 1 ) ;
}
2007-08-29 10:58:25 +04:00
write_byte ( cli , fd , 0 , num_locks ) ;
lock_byte ( cli , fd , 0 , lock_timeout ) ;
2007-08-29 09:45:24 +04:00
2009-11-24 12:18:37 +03:00
start = timeval_current ( ) ;
2007-08-29 10:58:25 +04:00
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 09:45:24 +04:00
2007-08-29 10:58:25 +04:00
if ( do_reads ) {
uint8_t c ;
read_byte ( cli , fd , & c , i ) ;
incr = c - val [ i ] ;
2024-05-31 22:28:50 +03:00
val [ i ] = c ;
2007-08-29 09:45:24 +04:00
}
2007-08-29 10:58:25 +04: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 ) ;
}
2009-11-24 12:18:37 +03:00
if ( timeval_elapsed ( & start ) > 1.0 ) {
2024-05-31 22:28:50 +03:00
printf ( " %8u locks/sec \r " ,
2009-11-24 12:18:37 +03:00
( unsigned ) ( 2 * count / timeval_elapsed ( & start ) ) ) ;
2007-08-29 10:58:25 +04:00
fflush ( stdout ) ;
2009-11-24 12:18:37 +03:00
start = timeval_current ( ) ;
2007-08-29 10:58:25 +04:00
count = 0 ;
}
loops + + ;
}
2007-08-29 09:45:24 +04:00
}