2004-03-09 05:13:13 +03:00
/*
Unix SMB / CIFS implementation .
SMB torture tester - NBENCH test
Copyright ( C ) Andrew Tridgell 1997 - 2004
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-03-09 05:13:13 +03:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-03-09 05:13:13 +03:00
*/
# include "includes.h"
2006-01-03 18:40:05 +03:00
# include "libcli/libcli.h"
2006-10-16 17:06:41 +04:00
# include "torture/ui.h"
2006-03-17 20:59:58 +03:00
# include "torture/util.h"
# include "torture/torture.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2007-06-17 23:35:00 +04:00
# include "system/locale.h"
2005-02-10 08:09:35 +03:00
# include "pstring.h"
2004-03-09 05:13:13 +03:00
2006-02-04 17:08:24 +03:00
# include "torture/nbench/proto.h"
2004-03-09 05:13:13 +03:00
int nbench_line_count = 0 ;
2004-03-09 05:24:14 +03:00
static int timelimit = 600 ;
2004-03-10 06:24:03 +03:00
static int warmup ;
2004-06-14 03:50:55 +04:00
static const char * loadfile ;
2006-12-21 08:34:26 +03:00
static int read_only ;
2004-03-09 05:13:13 +03:00
2006-12-21 09:48:42 +03:00
# define ival(s) strtoll(s, NULL, 0)
2004-03-09 05:13:13 +03:00
2007-08-27 15:17:48 +04:00
static unsigned long nb_max_retries ;
# define NB_RETRY(op) \
for ( n = 0 ; n < = nb_max_retries & & ! op ; n + + ) do_reconnect ( & cli , client )
static void do_reconnect ( struct smbcli_state * * cli , int client )
{
int n ;
printf ( " [%d] Reconnecting client %d \n " , nbench_line_count , client ) ;
for ( n = 0 ; n < nb_max_retries ; n + + ) {
if ( nb_reconnect ( cli , client ) ) {
printf ( " [%d] Reconnected client %d \n " , nbench_line_count , client ) ;
return ;
}
}
printf ( " [%d] Failed to reconnect client %d \n " , nbench_line_count , client ) ;
nb_exit ( 1 ) ;
}
2004-03-09 05:13:13 +03:00
/* run a test that simulates an approximate netbench client load */
2007-10-07 02:28:14 +04:00
static bool run_netbench ( struct torture_context * tctx , struct smbcli_state * cli , int client )
2004-03-09 05:13:13 +03:00
{
2007-08-26 22:24:12 +04:00
int torture_nprocs = torture_setting_int ( tctx , " nprocs " , 4 ) ;
2004-03-09 05:13:13 +03:00
int i ;
pstring line ;
char * cname ;
FILE * f ;
2007-10-07 02:28:14 +04:00
bool correct = true ;
2007-08-28 04:16:58 +04:00
double target_rate = torture_setting_double ( tctx , " targetrate " , 0 ) ;
2007-08-27 15:17:48 +04:00
int n ;
2007-06-18 00:03:31 +04:00
2007-06-18 01:54:11 +04:00
if ( target_rate ! = 0 & & client = = 0 ) {
2007-06-18 00:03:31 +04:00
printf ( " Targetting %.4f MByte/sec \n " , target_rate ) ;
}
2004-11-03 13:09:48 +03:00
2007-08-27 15:17:48 +04:00
nb_setup ( cli , client ) ;
2005-06-02 03:10:11 +04:00
if ( torture_nprocs = = 1 ) {
2007-08-27 15:17:48 +04:00
if ( ! read_only ) {
NB_RETRY ( torture_setup_dir ( cli , " \\ clients " ) ) ;
2005-06-02 03:10:11 +04:00
}
}
2004-03-26 05:09:51 +03:00
asprintf ( & cname , " client%d " , client + 1 ) ;
2004-03-09 05:13:13 +03:00
f = fopen ( loadfile , " r " ) ;
if ( ! f ) {
perror ( loadfile ) ;
2007-10-07 02:28:14 +04:00
return false ;
2004-03-09 05:13:13 +03:00
}
again :
2007-06-17 23:35:00 +04:00
nbio_time_reset ( ) ;
2004-03-09 05:13:13 +03:00
while ( fgets ( line , sizeof ( line ) - 1 , f ) ) {
NTSTATUS status ;
2007-06-17 23:35:00 +04:00
const char * * params0 , * * params ;
2004-03-10 06:24:03 +03:00
2004-03-09 05:13:13 +03:00
nbench_line_count + + ;
line [ strlen ( line ) - 1 ] = 0 ;
all_string_sub ( line , " client1 " , cname , sizeof ( line ) ) ;
2007-06-17 23:35:00 +04:00
params = params0 = str_list_make_shell ( NULL , line , " " ) ;
2005-10-01 01:48:25 +04:00
i = str_list_length ( params ) ;
2004-03-09 05:13:13 +03:00
2007-06-17 23:35:00 +04:00
if ( i > 0 & & isdigit ( params [ 0 ] [ 0 ] ) ) {
double targett = strtod ( params [ 0 ] , NULL ) ;
2007-06-18 00:04:57 +04:00
if ( target_rate ! = 0 ) {
nbio_target_rate ( target_rate ) ;
} else {
nbio_time_delay ( targett ) ;
}
2007-06-17 23:35:00 +04:00
params + + ;
i - - ;
2007-06-18 00:03:31 +04:00
} else if ( target_rate ! = 0 ) {
nbio_target_rate ( target_rate ) ;
2007-06-17 23:35:00 +04:00
}
2004-03-09 05:13:13 +03:00
if ( i < 2 | | params [ 0 ] [ 0 ] = = ' # ' ) continue ;
if ( ! strncmp ( params [ 0 ] , " SMB " , 3 ) ) {
printf ( " ERROR: You are using a dbench 1 load file \n " ) ;
2007-08-27 15:17:48 +04:00
nb_exit ( 1 ) ;
2004-03-09 05:13:13 +03:00
}
2007-06-18 01:54:11 +04:00
if ( strncmp ( params [ i - 1 ] , " NT_STATUS_ " , 10 ) ! = 0 & &
strncmp ( params [ i - 1 ] , " 0x " , 2 ) ! = 0 ) {
2004-03-09 05:13:13 +03:00
printf ( " Badly formed status at line %d \n " , nbench_line_count ) ;
2005-10-01 01:48:25 +04:00
talloc_free ( params ) ;
2004-03-09 05:13:13 +03:00
continue ;
}
2007-06-18 01:54:11 +04:00
/* accept numeric or string status codes */
if ( strncmp ( params [ i - 1 ] , " 0x " , 2 ) = = 0 ) {
status = NT_STATUS ( strtoul ( params [ i - 1 ] , NULL , 16 ) ) ;
} else {
status = nt_status_string_to_code ( params [ i - 1 ] ) ;
}
2004-03-09 05:13:13 +03:00
DEBUG ( 9 , ( " run_netbench(%d): %s %s \n " , client , params [ 0 ] , params [ 1 ] ) ) ;
if ( ! strcmp ( params [ 0 ] , " NTCreateX " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_createx ( params [ 1 ] , ival ( params [ 2 ] ) , ival ( params [ 3 ] ) ,
ival ( params [ 4 ] ) , status ) ) ;
2004-03-09 05:13:13 +03:00
} else if ( ! strcmp ( params [ 0 ] , " Close " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_close ( ival ( params [ 1 ] ) , status ) ) ;
2006-12-21 08:34:26 +03:00
} else if ( ! read_only & & ! strcmp ( params [ 0 ] , " Rename " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_rename ( params [ 1 ] , params [ 2 ] , status , n > 0 ) ) ;
2006-12-21 08:34:26 +03:00
} else if ( ! read_only & & ! strcmp ( params [ 0 ] , " Unlink " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_unlink ( params [ 1 ] , ival ( params [ 2 ] ) , status , n > 0 ) ) ;
2006-12-21 08:34:26 +03:00
} else if ( ! read_only & & ! strcmp ( params [ 0 ] , " Deltree " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_deltree ( params [ 1 ] , n > 0 ) ) ;
2006-12-21 08:34:26 +03:00
} else if ( ! read_only & & ! strcmp ( params [ 0 ] , " Rmdir " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_rmdir ( params [ 1 ] , status , n > 0 ) ) ;
2006-12-21 08:34:26 +03:00
} else if ( ! read_only & & ! strcmp ( params [ 0 ] , " Mkdir " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_mkdir ( params [ 1 ] , status , n > 0 ) ) ;
2004-03-09 05:13:13 +03:00
} else if ( ! strcmp ( params [ 0 ] , " QUERY_PATH_INFORMATION " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_qpathinfo ( params [ 1 ] , ival ( params [ 2 ] ) , status ) ) ;
2004-03-09 05:13:13 +03:00
} else if ( ! strcmp ( params [ 0 ] , " QUERY_FILE_INFORMATION " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_qfileinfo ( ival ( params [ 1 ] ) , ival ( params [ 2 ] ) , status ) ) ;
2004-03-09 05:13:13 +03:00
} else if ( ! strcmp ( params [ 0 ] , " QUERY_FS_INFORMATION " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_qfsinfo ( ival ( params [ 1 ] ) , status ) ) ;
2006-12-21 08:34:26 +03:00
} else if ( ! read_only & & ! strcmp ( params [ 0 ] , " SET_FILE_INFORMATION " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_sfileinfo ( ival ( params [ 1 ] ) , ival ( params [ 2 ] ) , status ) ) ;
2004-03-09 05:13:13 +03:00
} else if ( ! strcmp ( params [ 0 ] , " FIND_FIRST " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_findfirst ( params [ 1 ] , ival ( params [ 2 ] ) ,
ival ( params [ 3 ] ) , ival ( params [ 4 ] ) , status ) ) ;
2006-12-21 08:34:26 +03:00
} else if ( ! read_only & & ! strcmp ( params [ 0 ] , " WriteX " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_writex ( ival ( params [ 1 ] ) ,
ival ( params [ 2 ] ) , ival ( params [ 3 ] ) , ival ( params [ 4 ] ) ,
status ) ) ;
2006-12-21 08:34:26 +03:00
} else if ( ! read_only & & ! strcmp ( params [ 0 ] , " Write " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_write ( ival ( params [ 1 ] ) ,
ival ( params [ 2 ] ) , ival ( params [ 3 ] ) , ival ( params [ 4 ] ) ,
status ) ) ;
2004-03-09 05:13:13 +03:00
} else if ( ! strcmp ( params [ 0 ] , " LockX " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_lockx ( ival ( params [ 1 ] ) ,
ival ( params [ 2 ] ) , ival ( params [ 3 ] ) , status ) ) ;
2004-03-09 05:13:13 +03:00
} else if ( ! strcmp ( params [ 0 ] , " UnlockX " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_unlockx ( ival ( params [ 1 ] ) ,
ival ( params [ 2 ] ) , ival ( params [ 3 ] ) , status ) ) ;
2004-03-09 05:13:13 +03:00
} else if ( ! strcmp ( params [ 0 ] , " ReadX " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_readx ( ival ( params [ 1 ] ) ,
ival ( params [ 2 ] ) , ival ( params [ 3 ] ) , ival ( params [ 4 ] ) ,
status ) ) ;
2004-03-09 05:13:13 +03:00
} else if ( ! strcmp ( params [ 0 ] , " Flush " ) ) {
2007-08-27 15:17:48 +04:00
NB_RETRY ( nb_flush ( ival ( params [ 1 ] ) , status ) ) ;
2004-10-18 17:58:41 +04:00
} else if ( ! strcmp ( params [ 0 ] , " Sleep " ) ) {
nb_sleep ( ival ( params [ 1 ] ) , status ) ;
2004-03-09 05:13:13 +03:00
} else {
printf ( " [%d] Unknown operation %s \n " , nbench_line_count , params [ 0 ] ) ;
}
2005-10-01 01:48:25 +04:00
2007-08-27 15:17:48 +04:00
if ( n > nb_max_retries ) {
printf ( " Maximum reconnect retries reached for op '%s' \n " , params [ 0 ] ) ;
nb_exit ( 1 ) ;
}
2007-06-17 23:35:00 +04:00
talloc_free ( params0 ) ;
2004-11-26 02:05:43 +03:00
if ( nb_tick ( ) ) goto done ;
2004-03-09 05:13:13 +03:00
}
rewind ( f ) ;
goto again ;
done :
fclose ( f ) ;
2006-12-21 08:34:26 +03:00
if ( ! read_only & & torture_nprocs = = 1 ) {
2005-06-02 03:41:43 +04:00
smbcli_deltree ( cli - > tree , " \\ clients " ) ;
}
2004-03-09 05:13:13 +03:00
if ( ! torture_close_connection ( cli ) ) {
2007-10-07 02:28:14 +04:00
correct = false ;
2004-03-09 05:13:13 +03:00
}
return correct ;
}
/* run a test that simulates an approximate netbench client load */
2007-10-07 02:28:14 +04:00
bool torture_nbench ( struct torture_context * torture )
2004-03-09 05:13:13 +03:00
{
2007-10-07 02:28:14 +04:00
bool correct = true ;
2007-08-26 22:24:12 +04:00
int torture_nprocs = torture_setting_int ( torture , " nprocs " , 4 ) ;
2004-08-04 17:23:35 +04:00
struct smbcli_state * cli ;
2004-06-14 03:50:55 +04:00
const char * p ;
2004-03-09 05:13:13 +03:00
2007-10-07 02:28:14 +04:00
read_only = torture_setting_bool ( torture , " readonly " , false ) ;
2006-12-21 08:34:26 +03:00
2007-08-28 04:16:58 +04:00
nb_max_retries = torture_setting_int ( torture , " nretries " , 1 ) ;
2007-08-27 15:17:48 +04:00
2006-10-18 18:23:19 +04:00
p = torture_setting_string ( torture , " timelimit " , NULL ) ;
2004-03-09 05:13:13 +03:00
if ( p & & * p ) {
timelimit = atoi ( p ) ;
}
2004-03-10 06:24:03 +03:00
warmup = timelimit / 20 ;
2006-10-18 18:23:19 +04:00
loadfile = torture_setting_string ( torture , " loadfile " , NULL ) ;
2004-03-09 05:13:13 +03:00
if ( ! loadfile | | ! * loadfile ) {
loadfile = " client.txt " ;
}
2005-06-02 03:10:11 +04:00
if ( torture_nprocs > 1 ) {
2006-07-10 12:00:06 +04:00
if ( ! torture_open_connection ( & cli , 0 ) ) {
2007-10-07 02:28:14 +04:00
return false ;
2005-06-02 03:10:11 +04:00
}
2004-03-09 05:13:13 +03:00
2006-12-21 08:34:26 +03:00
if ( ! read_only & & ! torture_setup_dir ( cli , " \\ clients " ) ) {
2007-10-07 02:28:14 +04:00
return false ;
2005-06-02 03:10:11 +04:00
}
2004-11-26 02:05:43 +03:00
}
2004-03-09 05:13:13 +03:00
2004-11-26 02:05:43 +03:00
nbio_shmem ( torture_nprocs , timelimit , warmup ) ;
2004-03-09 05:13:13 +03:00
2004-03-10 06:24:03 +03:00
printf ( " Running for %d seconds with load '%s' and warmup %d secs \n " ,
timelimit , loadfile , warmup ) ;
2004-03-09 05:13:13 +03:00
2005-06-09 12:58:12 +04:00
/* we need to reset SIGCHLD here as the name resolution
library may have changed it . We rely on correct signals
from childs in the main torture code which reaps
children . This is why smbtorture BENCH - NBENCH was sometimes
failing */
signal ( SIGCHLD , SIG_DFL ) ;
2004-10-28 17:40:50 +04:00
signal ( SIGALRM , nb_alarm ) ;
2004-03-09 05:13:13 +03:00
alarm ( 1 ) ;
2006-10-16 17:06:41 +04:00
torture_create_procs ( torture , run_netbench , & correct ) ;
2004-03-09 05:13:13 +03:00
alarm ( 0 ) ;
2006-12-21 08:34:26 +03:00
if ( ! read_only & & torture_nprocs > 1 ) {
2005-06-02 03:41:43 +04:00
smbcli_deltree ( cli - > tree , " \\ clients " ) ;
}
2004-11-26 02:05:43 +03:00
printf ( " \n Throughput %g MB/sec \n " , nbio_result ( ) ) ;
2004-03-09 05:13:13 +03:00
return correct ;
}
2006-06-17 06:20:39 +04:00
NTSTATUS torture_nbench_init ( void )
{
2007-08-27 15:17:48 +04:00
struct torture_suite * suite =
torture_suite_create (
talloc_autofree_context ( ) ,
" BENCH " ) ;
2006-10-16 17:06:41 +04:00
torture_suite_add_simple_test ( suite , " NBENCH " , torture_nbench ) ;
2007-08-27 15:17:48 +04:00
suite - > description = talloc_strdup ( suite , " Benchmarks " ) ;
2006-10-16 17:06:41 +04:00
torture_register_suite ( suite ) ;
2006-06-17 06:20:39 +04:00
return NT_STATUS_OK ;
}