1*5184Sek110237 2*5184Sek110237 /* 3*5184Sek110237 * CDDL HEADER START 4*5184Sek110237 * 5*5184Sek110237 * The contents of this file are subject to the terms of the 6*5184Sek110237 * Common Development and Distribution License (the "License"). 7*5184Sek110237 * You may not use this file except in compliance with the License. 8*5184Sek110237 * 9*5184Sek110237 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*5184Sek110237 * or http://www.opensolaris.org/os/licensing. 11*5184Sek110237 * See the License for the specific language governing permissions 12*5184Sek110237 * and limitations under the License. 13*5184Sek110237 * 14*5184Sek110237 * When distributing Covered Code, include this CDDL HEADER in each 15*5184Sek110237 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*5184Sek110237 * If applicable, add the following below this CDDL HEADER, with the 17*5184Sek110237 * fields enclosed by brackets "[]" replaced with your own identifying 18*5184Sek110237 * information: Portions Copyright [yyyy] [name of copyright owner] 19*5184Sek110237 * 20*5184Sek110237 * CDDL HEADER END 21*5184Sek110237 */ 22*5184Sek110237 /* 23*5184Sek110237 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24*5184Sek110237 * Use is subject to license terms. 25*5184Sek110237 */ 26*5184Sek110237 27*5184Sek110237 %{ 28*5184Sek110237 #pragma ident "%Z%%M% %I% %E% SMI" 29*5184Sek110237 %} 30*5184Sek110237 31*5184Sek110237 %{ 32*5184Sek110237 33*5184Sek110237 #include <stdlib.h> 34*5184Sek110237 #include <stdio.h> 35*5184Sek110237 #include <string.h> 36*5184Sek110237 #include <signal.h> 37*5184Sek110237 #include <errno.h> 38*5184Sek110237 #include <sys/types.h> 39*5184Sek110237 #include <locale.h> 40*5184Sek110237 #include <sys/utsname.h> 41*5184Sek110237 #ifdef HAVE_STDINT_H 42*5184Sek110237 #include <stdint.h> 43*5184Sek110237 #endif 44*5184Sek110237 #include <fcntl.h> 45*5184Sek110237 #include <sys/mman.h> 46*5184Sek110237 #include <sys/wait.h> 47*5184Sek110237 #ifdef HAVE_LIBTECLA 48*5184Sek110237 #include <libtecla.h> 49*5184Sek110237 #endif 50*5184Sek110237 #include "parsertypes.h" 51*5184Sek110237 #include "filebench.h" 52*5184Sek110237 #include "utils.h" 53*5184Sek110237 #include "stats.h" 54*5184Sek110237 #include "vars.h" 55*5184Sek110237 #include "eventgen.h" 56*5184Sek110237 #ifdef HAVE_LIBTECLA 57*5184Sek110237 #include "auto_comp.h" 58*5184Sek110237 #endif 59*5184Sek110237 60*5184Sek110237 int dofile = FS_FALSE; 61*5184Sek110237 static const char cmdname[] = "filebench"; 62*5184Sek110237 static const char cmd_options[] = "pa:f:hi:s:m:"; 63*5184Sek110237 static void usage(int); 64*5184Sek110237 65*5184Sek110237 static cmd_t *cmd = NULL; /* Command being processed */ 66*5184Sek110237 #ifdef HAVE_LIBTECLA 67*5184Sek110237 static GetLine *gl; /* GetLine resource object */ 68*5184Sek110237 #endif 69*5184Sek110237 70*5184Sek110237 char *execname; 71*5184Sek110237 char *fscriptname; 72*5184Sek110237 int noproc = 0; 73*5184Sek110237 var_t *var_list = NULL; 74*5184Sek110237 pidlist_t *pidlist = NULL; 75*5184Sek110237 char *cwd = NULL; 76*5184Sek110237 FILE *parentscript = NULL; 77*5184Sek110237 78*5184Sek110237 /* yacc externals */ 79*5184Sek110237 extern FILE *yyin; 80*5184Sek110237 extern int yydebug; 81*5184Sek110237 extern void yyerror(char *s); 82*5184Sek110237 83*5184Sek110237 /* utilities */ 84*5184Sek110237 static void terminate(void); 85*5184Sek110237 static cmd_t *alloc_cmd(void); 86*5184Sek110237 static attr_t *alloc_attr(void); 87*5184Sek110237 static attr_t *get_attr(cmd_t *cmd, int64_t name); 88*5184Sek110237 static attr_t *get_attr_integer(cmd_t *cmd, int64_t name); 89*5184Sek110237 static attr_t *get_attr_bool(cmd_t *cmd, int64_t name); 90*5184Sek110237 static var_t *alloc_var(void); 91*5184Sek110237 static var_t *get_var(cmd_t *cmd, int64_t name); 92*5184Sek110237 static list_t *alloc_list(); 93*5184Sek110237 94*5184Sek110237 /* Info Commands */ 95*5184Sek110237 static void parser_show(cmd_t *); 96*5184Sek110237 static void parser_list(cmd_t *); 97*5184Sek110237 98*5184Sek110237 /* Define Commands */ 99*5184Sek110237 static void parser_proc_define(cmd_t *); 100*5184Sek110237 static void parser_thread_define(cmd_t *, procflow_t *, int instances); 101*5184Sek110237 static void parser_flowop_define(cmd_t *, threadflow_t *); 102*5184Sek110237 static void parser_file_define(cmd_t *); 103*5184Sek110237 static void parser_fileset_define(cmd_t *); 104*5184Sek110237 105*5184Sek110237 /* Create Commands */ 106*5184Sek110237 static void parser_proc_create(cmd_t *); 107*5184Sek110237 static void parser_thread_create(cmd_t *); 108*5184Sek110237 static void parser_flowop_create(cmd_t *); 109*5184Sek110237 static void parser_file_create(cmd_t *); 110*5184Sek110237 static void parser_fileset_create(cmd_t *); 111*5184Sek110237 112*5184Sek110237 /* Shutdown Commands */ 113*5184Sek110237 static void parser_proc_shutdown(cmd_t *); 114*5184Sek110237 static void parser_filebench_shutdown(cmd_t *cmd); 115*5184Sek110237 116*5184Sek110237 /* Other Commands */ 117*5184Sek110237 static void parser_foreach_integer(cmd_t *cmd); 118*5184Sek110237 static void parser_foreach_string(cmd_t *cmd); 119*5184Sek110237 static void parser_sleep(cmd_t *cmd); 120*5184Sek110237 static void parser_sleep_variable(cmd_t *cmd); 121*5184Sek110237 static void parser_log(cmd_t *cmd); 122*5184Sek110237 static void parser_statscmd(cmd_t *cmd); 123*5184Sek110237 static void parser_statsdump(cmd_t *cmd); 124*5184Sek110237 static void parser_statsxmldump(cmd_t *cmd); 125*5184Sek110237 static void parser_echo(cmd_t *cmd); 126*5184Sek110237 static void parser_usage(cmd_t *cmd); 127*5184Sek110237 static void parser_vars(cmd_t *cmd); 128*5184Sek110237 static void parser_printvars(cmd_t *cmd); 129*5184Sek110237 static void parser_system(cmd_t *cmd); 130*5184Sek110237 static void parser_statssnap(cmd_t *cmd); 131*5184Sek110237 static void parser_directory(cmd_t *cmd); 132*5184Sek110237 static void parser_eventgen(cmd_t *cmd); 133*5184Sek110237 static void parser_run(cmd_t *cmd); 134*5184Sek110237 static void parser_run_variable(cmd_t *cmd); 135*5184Sek110237 static void parser_help(cmd_t *cmd); 136*5184Sek110237 static void arg_parse(const char *command); 137*5184Sek110237 static void parser_abort(int arg); 138*5184Sek110237 139*5184Sek110237 %} 140*5184Sek110237 141*5184Sek110237 %union { 142*5184Sek110237 int64_t ival; 143*5184Sek110237 uchar_t bval; 144*5184Sek110237 char * sval; 145*5184Sek110237 fs_u val; 146*5184Sek110237 cmd_t *cmd; 147*5184Sek110237 attr_t *attr; 148*5184Sek110237 list_t *list; 149*5184Sek110237 } 150*5184Sek110237 151*5184Sek110237 %start commands 152*5184Sek110237 153*5184Sek110237 %token FSC_LIST FSC_DEFINE FSC_EXEC FSC_QUIT FSC_DEBUG FSC_CREATE 154*5184Sek110237 %token FSC_SLEEP FSC_STATS FSC_FOREACH FSC_SET FSC_SHUTDOWN FSC_LOG 155*5184Sek110237 %token FSC_SYSTEM FSC_FLOWOP FSC_EVENTGEN FSC_ECHO FSC_LOAD FSC_RUN 156*5184Sek110237 %token FSC_USAGE FSC_HELP FSC_VARS 157*5184Sek110237 %token FSV_STRING FSV_VAL_INT FSV_VAL_BOOLEAN FSV_VARIABLE FSV_WHITESTRING 158*5184Sek110237 %token FST_INT FST_BOOLEAN 159*5184Sek110237 %token FSE_FILE FSE_PROC FSE_THREAD FSE_CLEAR FSE_ALL FSE_SNAP FSE_DUMP 160*5184Sek110237 %token FSE_DIRECTORY FSE_COMMAND FSE_FILESET FSE_XMLDUMP 161*5184Sek110237 %token FSK_SEPLST FSK_OPENLST FSK_CLOSELST FSK_ASSIGN FSK_IN FSK_QUOTE 162*5184Sek110237 %token FSK_DIRSEPLST 163*5184Sek110237 %token FSA_SIZE FSA_PREALLOC FSA_PARALLOC FSA_PATH FSA_REUSE 164*5184Sek110237 %token FSA_PROCESS FSA_MEMSIZE FSA_RATE FSA_CACHED 165*5184Sek110237 %token FSA_IOSIZE FSA_FILE FSA_WSS FSA_NAME FSA_RANDOM FSA_INSTANCES 166*5184Sek110237 %token FSA_DSYNC FSA_TARGET FSA_ITERS FSA_NICE FSA_VALUE FSA_BLOCKING 167*5184Sek110237 %token FSA_HIGHWATER FSA_DIRECTIO FSA_DIRWIDTH FSA_FD FSA_SRCFD FSA_ROTATEFD 168*5184Sek110237 %token FSA_NAMELENGTH FSA_FILESIZE FSA_ENTRIES FSA_FILESIZEGAMMA 169*5184Sek110237 %token FSA_DIRGAMMA FSA_USEISM 170*5184Sek110237 171*5184Sek110237 %type <ival> FSV_VAL_INT 172*5184Sek110237 %type <bval> FSV_VAL_BOOLEAN 173*5184Sek110237 %type <sval> FSV_STRING 174*5184Sek110237 %type <sval> FSV_WHITESTRING 175*5184Sek110237 %type <sval> FSV_VARIABLE 176*5184Sek110237 %type <sval> FSK_ASSIGN 177*5184Sek110237 178*5184Sek110237 %type <ival> FSC_LIST FSC_DEFINE FSC_SET FSC_LOAD FSC_RUN 179*5184Sek110237 %type <ival> FSE_FILE FSE_PROC FSE_THREAD FSE_CLEAR FSC_HELP 180*5184Sek110237 181*5184Sek110237 %type <sval> name 182*5184Sek110237 %type <ival> entity 183*5184Sek110237 %type <val> value 184*5184Sek110237 185*5184Sek110237 %type <cmd> command inner_commands load_command run_command 186*5184Sek110237 %type <cmd> list_command define_command debug_command create_command 187*5184Sek110237 %type <cmd> sleep_command stats_command set_command shutdown_command 188*5184Sek110237 %type <cmd> foreach_command log_command system_command flowop_command 189*5184Sek110237 %type <cmd> eventgen_command quit_command flowop_list thread_list 190*5184Sek110237 %type <cmd> thread echo_command usage_command help_command vars_command 191*5184Sek110237 192*5184Sek110237 %type <attr> attr_op attr_ops 193*5184Sek110237 %type <attr> attr_value 194*5184Sek110237 %type <list> integer_seplist string_seplist string_list var_string_list var_string 195*5184Sek110237 %type <list> whitevar_string whitevar_string_list 196*5184Sek110237 %type <ival> attrs_define_file attrs_define_thread attrs_flowop attrs_define_fileset 197*5184Sek110237 %type <ival> attrs_define_proc attrs_eventgen 198*5184Sek110237 %type <ival> attr_name 199*5184Sek110237 200*5184Sek110237 %% 201*5184Sek110237 202*5184Sek110237 commands: commands command 203*5184Sek110237 { 204*5184Sek110237 list_t *list = NULL; 205*5184Sek110237 list_t *list_end = NULL; 206*5184Sek110237 207*5184Sek110237 if ($2->cmd != NULL) 208*5184Sek110237 $2->cmd($2); 209*5184Sek110237 210*5184Sek110237 free($2); 211*5184Sek110237 } 212*5184Sek110237 | commands error 213*5184Sek110237 { 214*5184Sek110237 if (dofile) 215*5184Sek110237 YYABORT; 216*5184Sek110237 } 217*5184Sek110237 |; 218*5184Sek110237 219*5184Sek110237 inner_commands: command 220*5184Sek110237 { 221*5184Sek110237 filebench_log(LOG_DEBUG_IMPL, "inner_command %zx", $1); 222*5184Sek110237 $$ = $1; 223*5184Sek110237 } 224*5184Sek110237 | inner_commands command 225*5184Sek110237 { 226*5184Sek110237 cmd_t *list = NULL; 227*5184Sek110237 cmd_t *list_end = NULL; 228*5184Sek110237 229*5184Sek110237 /* Find end of list */ 230*5184Sek110237 for (list = $1; list != NULL; 231*5184Sek110237 list = list->cmd_next) 232*5184Sek110237 list_end = list; 233*5184Sek110237 234*5184Sek110237 list_end->cmd_next = $2; 235*5184Sek110237 236*5184Sek110237 filebench_log(LOG_DEBUG_IMPL, 237*5184Sek110237 "inner_commands adding cmd %zx to list %zx", $2, $1); 238*5184Sek110237 239*5184Sek110237 $$ = $1; 240*5184Sek110237 }; 241*5184Sek110237 242*5184Sek110237 command: 243*5184Sek110237 define_command 244*5184Sek110237 | debug_command 245*5184Sek110237 | eventgen_command 246*5184Sek110237 | create_command 247*5184Sek110237 | echo_command 248*5184Sek110237 | usage_command 249*5184Sek110237 | vars_command 250*5184Sek110237 | foreach_command 251*5184Sek110237 | help_command 252*5184Sek110237 | list_command 253*5184Sek110237 | load_command 254*5184Sek110237 | log_command 255*5184Sek110237 | run_command 256*5184Sek110237 | set_command 257*5184Sek110237 | shutdown_command 258*5184Sek110237 | sleep_command 259*5184Sek110237 | stats_command 260*5184Sek110237 | system_command 261*5184Sek110237 | quit_command; 262*5184Sek110237 263*5184Sek110237 foreach_command: FSC_FOREACH 264*5184Sek110237 { 265*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 266*5184Sek110237 YYERROR; 267*5184Sek110237 filebench_log(LOG_DEBUG_IMPL, "foreach_command %zx", $$); 268*5184Sek110237 } 269*5184Sek110237 | foreach_command FSV_VARIABLE FSK_IN integer_seplist FSK_OPENLST inner_commands FSK_CLOSELST 270*5184Sek110237 { 271*5184Sek110237 cmd_t *cmd, *inner_cmd; 272*5184Sek110237 list_t *list; 273*5184Sek110237 274*5184Sek110237 $$ = $1; 275*5184Sek110237 $$->cmd_list = $6; 276*5184Sek110237 $$->cmd_tgt1 = $2; 277*5184Sek110237 $$->cmd_param_list = $4; 278*5184Sek110237 $$->cmd = parser_foreach_integer; 279*5184Sek110237 280*5184Sek110237 for (list = $$->cmd_param_list; list != NULL; 281*5184Sek110237 list = list->list_next) { 282*5184Sek110237 for (inner_cmd = $$->cmd_list; 283*5184Sek110237 inner_cmd != NULL; 284*5184Sek110237 inner_cmd = inner_cmd->cmd_next) { 285*5184Sek110237 filebench_log(LOG_DEBUG_IMPL, 286*5184Sek110237 "packing foreach: %zx %s=%lld, cmd %zx", 287*5184Sek110237 $$, 288*5184Sek110237 $$->cmd_tgt1, 289*5184Sek110237 *list->list_integer, inner_cmd); 290*5184Sek110237 } 291*5184Sek110237 } 292*5184Sek110237 }| foreach_command FSV_VARIABLE FSK_IN string_seplist FSK_OPENLST inner_commands FSK_CLOSELST 293*5184Sek110237 { 294*5184Sek110237 cmd_t *cmd, *inner_cmd; 295*5184Sek110237 list_t *list; 296*5184Sek110237 297*5184Sek110237 $$ = $1; 298*5184Sek110237 $$->cmd_list = $6; 299*5184Sek110237 $$->cmd_tgt1 = $2; 300*5184Sek110237 $$->cmd_param_list = $4; 301*5184Sek110237 $$->cmd = parser_foreach_string; 302*5184Sek110237 303*5184Sek110237 for (list = $$->cmd_param_list; list != NULL; 304*5184Sek110237 list = list->list_next) { 305*5184Sek110237 for (inner_cmd = $$->cmd_list; 306*5184Sek110237 inner_cmd != NULL; 307*5184Sek110237 inner_cmd = inner_cmd->cmd_next) { 308*5184Sek110237 filebench_log(LOG_DEBUG_IMPL, 309*5184Sek110237 "packing foreach: %zx %s=%s, cmd %zx", 310*5184Sek110237 $$, 311*5184Sek110237 $$->cmd_tgt1, 312*5184Sek110237 *list->list_string, inner_cmd); 313*5184Sek110237 } 314*5184Sek110237 } 315*5184Sek110237 }; 316*5184Sek110237 317*5184Sek110237 integer_seplist: FSV_VAL_INT 318*5184Sek110237 { 319*5184Sek110237 if (($$ = alloc_list()) == NULL) 320*5184Sek110237 YYERROR; 321*5184Sek110237 322*5184Sek110237 $$->list_integer = integer_alloc($1); 323*5184Sek110237 } 324*5184Sek110237 | integer_seplist FSK_SEPLST FSV_VAL_INT 325*5184Sek110237 { 326*5184Sek110237 list_t *list = NULL; 327*5184Sek110237 list_t *list_end = NULL; 328*5184Sek110237 329*5184Sek110237 if (($$ = alloc_list()) == NULL) 330*5184Sek110237 YYERROR; 331*5184Sek110237 332*5184Sek110237 $$->list_integer = integer_alloc($3); 333*5184Sek110237 334*5184Sek110237 /* Find end of list */ 335*5184Sek110237 for (list = $1; list != NULL; 336*5184Sek110237 list = list->list_next) 337*5184Sek110237 list_end = list; 338*5184Sek110237 list_end->list_next = $$; 339*5184Sek110237 $$ = $1; 340*5184Sek110237 }; 341*5184Sek110237 342*5184Sek110237 string_seplist: FSK_QUOTE FSV_WHITESTRING FSK_QUOTE 343*5184Sek110237 { 344*5184Sek110237 if (($$ = alloc_list()) == NULL) 345*5184Sek110237 YYERROR; 346*5184Sek110237 347*5184Sek110237 $$->list_string = string_alloc($2); 348*5184Sek110237 } 349*5184Sek110237 | string_seplist FSK_SEPLST FSK_QUOTE FSV_WHITESTRING FSK_QUOTE 350*5184Sek110237 { 351*5184Sek110237 list_t *list = NULL; 352*5184Sek110237 list_t *list_end = NULL; 353*5184Sek110237 354*5184Sek110237 if (($$ = alloc_list()) == NULL) 355*5184Sek110237 YYERROR; 356*5184Sek110237 357*5184Sek110237 $$->list_string = string_alloc($4); 358*5184Sek110237 359*5184Sek110237 /* Find end of list */ 360*5184Sek110237 for (list = $1; list != NULL; 361*5184Sek110237 list = list->list_next) 362*5184Sek110237 list_end = list; 363*5184Sek110237 list_end->list_next = $$; 364*5184Sek110237 $$ = $1; 365*5184Sek110237 }; 366*5184Sek110237 367*5184Sek110237 eventgen_command: FSC_EVENTGEN 368*5184Sek110237 { 369*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 370*5184Sek110237 YYERROR; 371*5184Sek110237 $$->cmd = &parser_eventgen; 372*5184Sek110237 } 373*5184Sek110237 | eventgen_command attr_ops 374*5184Sek110237 { 375*5184Sek110237 $1->cmd_attr_list = $2; 376*5184Sek110237 }; 377*5184Sek110237 378*5184Sek110237 system_command: FSC_SYSTEM whitevar_string_list 379*5184Sek110237 { 380*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 381*5184Sek110237 YYERROR; 382*5184Sek110237 383*5184Sek110237 $$->cmd_param_list = $2; 384*5184Sek110237 $$->cmd = parser_system; 385*5184Sek110237 }; 386*5184Sek110237 387*5184Sek110237 echo_command: FSC_ECHO whitevar_string_list 388*5184Sek110237 { 389*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 390*5184Sek110237 YYERROR; 391*5184Sek110237 392*5184Sek110237 $$->cmd_param_list = $2; 393*5184Sek110237 $$->cmd = parser_echo; 394*5184Sek110237 }; 395*5184Sek110237 396*5184Sek110237 usage_command: FSC_USAGE whitevar_string_list 397*5184Sek110237 { 398*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 399*5184Sek110237 YYERROR; 400*5184Sek110237 401*5184Sek110237 $$->cmd_param_list = $2; 402*5184Sek110237 $$->cmd = parser_usage; 403*5184Sek110237 }; 404*5184Sek110237 405*5184Sek110237 vars_command: FSC_VARS 406*5184Sek110237 { 407*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 408*5184Sek110237 YYERROR; 409*5184Sek110237 410*5184Sek110237 $$->cmd = parser_printvars; 411*5184Sek110237 }; 412*5184Sek110237 413*5184Sek110237 string_list: FSV_VARIABLE 414*5184Sek110237 { 415*5184Sek110237 if (($$ = alloc_list()) == NULL) 416*5184Sek110237 YYERROR; 417*5184Sek110237 418*5184Sek110237 $$->list_string = string_alloc($1); 419*5184Sek110237 } 420*5184Sek110237 | string_list FSK_SEPLST FSV_VARIABLE 421*5184Sek110237 { 422*5184Sek110237 list_t *list = NULL; 423*5184Sek110237 list_t *list_end = NULL; 424*5184Sek110237 425*5184Sek110237 if (($$ = alloc_list()) == NULL) 426*5184Sek110237 YYERROR; 427*5184Sek110237 428*5184Sek110237 $$->list_string = string_alloc($3); 429*5184Sek110237 430*5184Sek110237 /* Find end of list */ 431*5184Sek110237 for (list = $1; list != NULL; 432*5184Sek110237 list = list->list_next) 433*5184Sek110237 list_end = list; 434*5184Sek110237 list_end->list_next = $$; 435*5184Sek110237 $$ = $1; 436*5184Sek110237 }; 437*5184Sek110237 438*5184Sek110237 var_string: FSV_VARIABLE 439*5184Sek110237 { 440*5184Sek110237 if (($$ = alloc_list()) == NULL) 441*5184Sek110237 YYERROR; 442*5184Sek110237 443*5184Sek110237 $$->list_string = string_alloc($1); 444*5184Sek110237 } 445*5184Sek110237 | FSV_STRING 446*5184Sek110237 { 447*5184Sek110237 if (($$ = alloc_list()) == NULL) 448*5184Sek110237 YYERROR; 449*5184Sek110237 450*5184Sek110237 $$->list_string = string_alloc($1); 451*5184Sek110237 }; 452*5184Sek110237 453*5184Sek110237 var_string_list: var_string 454*5184Sek110237 { 455*5184Sek110237 $$ = $1; 456*5184Sek110237 }| var_string FSV_STRING 457*5184Sek110237 { 458*5184Sek110237 list_t *list = NULL; 459*5184Sek110237 list_t *list_end = NULL; 460*5184Sek110237 461*5184Sek110237 /* Add string */ 462*5184Sek110237 if (($$ = alloc_list()) == NULL) 463*5184Sek110237 YYERROR; 464*5184Sek110237 465*5184Sek110237 $$->list_string = string_alloc($2); 466*5184Sek110237 467*5184Sek110237 /* Find end of list */ 468*5184Sek110237 for (list = $1; list != NULL; 469*5184Sek110237 list = list->list_next) 470*5184Sek110237 list_end = list; 471*5184Sek110237 list_end->list_next = $$; 472*5184Sek110237 $$ = $1; 473*5184Sek110237 474*5184Sek110237 }| var_string FSV_VARIABLE 475*5184Sek110237 { 476*5184Sek110237 list_t *list = NULL; 477*5184Sek110237 list_t *list_end = NULL; 478*5184Sek110237 479*5184Sek110237 /* Add variable */ 480*5184Sek110237 if (($$ = alloc_list()) == NULL) 481*5184Sek110237 YYERROR; 482*5184Sek110237 483*5184Sek110237 $$->list_string = string_alloc($2); 484*5184Sek110237 485*5184Sek110237 /* Find end of list */ 486*5184Sek110237 for (list = $1; list != NULL; 487*5184Sek110237 list = list->list_next) 488*5184Sek110237 list_end = list; 489*5184Sek110237 list_end->list_next = $$; 490*5184Sek110237 $$ = $1; 491*5184Sek110237 } |var_string_list FSV_STRING 492*5184Sek110237 { 493*5184Sek110237 list_t *list = NULL; 494*5184Sek110237 list_t *list_end = NULL; 495*5184Sek110237 496*5184Sek110237 /* Add string */ 497*5184Sek110237 if (($$ = alloc_list()) == NULL) 498*5184Sek110237 YYERROR; 499*5184Sek110237 500*5184Sek110237 $$->list_string = string_alloc($2); 501*5184Sek110237 502*5184Sek110237 /* Find end of list */ 503*5184Sek110237 for (list = $1; list != NULL; 504*5184Sek110237 list = list->list_next) 505*5184Sek110237 list_end = list; 506*5184Sek110237 list_end->list_next = $$; 507*5184Sek110237 $$ = $1; 508*5184Sek110237 509*5184Sek110237 }| var_string_list FSV_VARIABLE 510*5184Sek110237 { 511*5184Sek110237 list_t *list = NULL; 512*5184Sek110237 list_t *list_end = NULL; 513*5184Sek110237 514*5184Sek110237 /* Add variable */ 515*5184Sek110237 if (($$ = alloc_list()) == NULL) 516*5184Sek110237 YYERROR; 517*5184Sek110237 518*5184Sek110237 $$->list_string = string_alloc($2); 519*5184Sek110237 520*5184Sek110237 /* Find end of list */ 521*5184Sek110237 for (list = $1; list != NULL; 522*5184Sek110237 list = list->list_next) 523*5184Sek110237 list_end = list; 524*5184Sek110237 list_end->list_next = $$; 525*5184Sek110237 $$ = $1; 526*5184Sek110237 }; 527*5184Sek110237 528*5184Sek110237 whitevar_string: FSK_QUOTE FSV_VARIABLE 529*5184Sek110237 { 530*5184Sek110237 if (($$ = alloc_list()) == NULL) 531*5184Sek110237 YYERROR; 532*5184Sek110237 533*5184Sek110237 $$->list_string = string_alloc($2); 534*5184Sek110237 } 535*5184Sek110237 | FSK_QUOTE FSV_WHITESTRING 536*5184Sek110237 { 537*5184Sek110237 if (($$ = alloc_list()) == NULL) 538*5184Sek110237 YYERROR; 539*5184Sek110237 540*5184Sek110237 $$->list_string = string_alloc($2); 541*5184Sek110237 }; 542*5184Sek110237 543*5184Sek110237 whitevar_string_list: whitevar_string FSV_WHITESTRING 544*5184Sek110237 { 545*5184Sek110237 list_t *list = NULL; 546*5184Sek110237 list_t *list_end = NULL; 547*5184Sek110237 548*5184Sek110237 /* Add string */ 549*5184Sek110237 if (($$ = alloc_list()) == NULL) 550*5184Sek110237 YYERROR; 551*5184Sek110237 552*5184Sek110237 $$->list_string = string_alloc($2); 553*5184Sek110237 554*5184Sek110237 /* Find end of list */ 555*5184Sek110237 for (list = $1; list != NULL; 556*5184Sek110237 list = list->list_next) 557*5184Sek110237 list_end = list; 558*5184Sek110237 list_end->list_next = $$; 559*5184Sek110237 $$ = $1; 560*5184Sek110237 561*5184Sek110237 }| whitevar_string FSV_VARIABLE 562*5184Sek110237 { 563*5184Sek110237 list_t *list = NULL; 564*5184Sek110237 list_t *list_end = NULL; 565*5184Sek110237 566*5184Sek110237 /* Add variable */ 567*5184Sek110237 if (($$ = alloc_list()) == NULL) 568*5184Sek110237 YYERROR; 569*5184Sek110237 570*5184Sek110237 $$->list_string = string_alloc($2); 571*5184Sek110237 572*5184Sek110237 /* Find end of list */ 573*5184Sek110237 for (list = $1; list != NULL; 574*5184Sek110237 list = list->list_next) 575*5184Sek110237 list_end = list; 576*5184Sek110237 list_end->list_next = $$; 577*5184Sek110237 $$ = $1; 578*5184Sek110237 } |whitevar_string_list FSV_WHITESTRING 579*5184Sek110237 { 580*5184Sek110237 list_t *list = NULL; 581*5184Sek110237 list_t *list_end = NULL; 582*5184Sek110237 583*5184Sek110237 /* Add string */ 584*5184Sek110237 if (($$ = alloc_list()) == NULL) 585*5184Sek110237 YYERROR; 586*5184Sek110237 587*5184Sek110237 $$->list_string = string_alloc($2); 588*5184Sek110237 589*5184Sek110237 /* Find end of list */ 590*5184Sek110237 for (list = $1; list != NULL; 591*5184Sek110237 list = list->list_next) 592*5184Sek110237 list_end = list; 593*5184Sek110237 list_end->list_next = $$; 594*5184Sek110237 $$ = $1; 595*5184Sek110237 596*5184Sek110237 }| whitevar_string_list FSV_VARIABLE 597*5184Sek110237 { 598*5184Sek110237 list_t *list = NULL; 599*5184Sek110237 list_t *list_end = NULL; 600*5184Sek110237 601*5184Sek110237 /* Add variable */ 602*5184Sek110237 if (($$ = alloc_list()) == NULL) 603*5184Sek110237 YYERROR; 604*5184Sek110237 605*5184Sek110237 $$->list_string = string_alloc($2); 606*5184Sek110237 607*5184Sek110237 /* Find end of list */ 608*5184Sek110237 for (list = $1; list != NULL; 609*5184Sek110237 list = list->list_next) 610*5184Sek110237 list_end = list; 611*5184Sek110237 list_end->list_next = $$; 612*5184Sek110237 $$ = $1; 613*5184Sek110237 }| whitevar_string_list FSK_QUOTE 614*5184Sek110237 { 615*5184Sek110237 $$ = $1; 616*5184Sek110237 }| whitevar_string FSK_QUOTE 617*5184Sek110237 { 618*5184Sek110237 $$ = $1; 619*5184Sek110237 }; 620*5184Sek110237 621*5184Sek110237 list_command: FSC_LIST 622*5184Sek110237 { 623*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 624*5184Sek110237 YYERROR; 625*5184Sek110237 $$->cmd = &parser_list; 626*5184Sek110237 }; 627*5184Sek110237 628*5184Sek110237 log_command: FSC_LOG whitevar_string_list 629*5184Sek110237 { 630*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 631*5184Sek110237 YYERROR; 632*5184Sek110237 $$->cmd = &parser_log; 633*5184Sek110237 $$->cmd_param_list = $2; 634*5184Sek110237 }; 635*5184Sek110237 636*5184Sek110237 debug_command: FSC_DEBUG FSV_VAL_INT 637*5184Sek110237 { 638*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 639*5184Sek110237 YYERROR; 640*5184Sek110237 $$->cmd = NULL; 641*5184Sek110237 filebench_shm->debug_level = $2; 642*5184Sek110237 if (filebench_shm->debug_level > 9) 643*5184Sek110237 yydebug = 1; 644*5184Sek110237 }; 645*5184Sek110237 646*5184Sek110237 set_command: FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_VAL_INT 647*5184Sek110237 { 648*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 649*5184Sek110237 YYERROR; 650*5184Sek110237 var_assign_integer($2, $4); 651*5184Sek110237 if (parentscript) { 652*5184Sek110237 $$->cmd_tgt1 = $2; 653*5184Sek110237 parser_vars($$); 654*5184Sek110237 } 655*5184Sek110237 $$->cmd = NULL; 656*5184Sek110237 } 657*5184Sek110237 | FSC_SET FSV_VARIABLE FSK_ASSIGN FSK_QUOTE FSV_WHITESTRING FSK_QUOTE 658*5184Sek110237 { 659*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 660*5184Sek110237 YYERROR; 661*5184Sek110237 var_assign_string($2, $5); 662*5184Sek110237 if (parentscript) { 663*5184Sek110237 $$->cmd_tgt1 = $2; 664*5184Sek110237 parser_vars($$); 665*5184Sek110237 } 666*5184Sek110237 $$->cmd = NULL; 667*5184Sek110237 }| FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_STRING 668*5184Sek110237 { 669*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 670*5184Sek110237 YYERROR; 671*5184Sek110237 var_assign_string($2, $4); 672*5184Sek110237 if (parentscript) { 673*5184Sek110237 $$->cmd_tgt1 = $2; 674*5184Sek110237 parser_vars($$); 675*5184Sek110237 } 676*5184Sek110237 $$->cmd = NULL; 677*5184Sek110237 }| FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_VARIABLE 678*5184Sek110237 { 679*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 680*5184Sek110237 YYERROR; 681*5184Sek110237 var_assign_var($2, $4); 682*5184Sek110237 if (parentscript) { 683*5184Sek110237 $$->cmd_tgt1 = $2; 684*5184Sek110237 parser_vars($$); 685*5184Sek110237 } 686*5184Sek110237 $$->cmd = NULL; 687*5184Sek110237 }; 688*5184Sek110237 689*5184Sek110237 stats_command: FSC_STATS FSE_SNAP 690*5184Sek110237 { 691*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 692*5184Sek110237 YYERROR; 693*5184Sek110237 $$->cmd = (void (*)(struct cmd *))&parser_statssnap; 694*5184Sek110237 break; 695*5184Sek110237 696*5184Sek110237 } 697*5184Sek110237 | FSC_STATS FSE_CLEAR 698*5184Sek110237 { 699*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 700*5184Sek110237 YYERROR; 701*5184Sek110237 $$->cmd = (void (*)(struct cmd *))&stats_clear; 702*5184Sek110237 703*5184Sek110237 } 704*5184Sek110237 | FSC_STATS FSE_DIRECTORY var_string_list 705*5184Sek110237 { 706*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 707*5184Sek110237 YYERROR; 708*5184Sek110237 $$->cmd_param_list = $3; 709*5184Sek110237 $$->cmd = (void (*)(struct cmd *))&parser_directory; 710*5184Sek110237 711*5184Sek110237 } 712*5184Sek110237 | FSC_STATS FSE_COMMAND whitevar_string_list 713*5184Sek110237 { 714*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 715*5184Sek110237 YYERROR; 716*5184Sek110237 717*5184Sek110237 $$->cmd_param_list = $3; 718*5184Sek110237 $$->cmd = parser_statscmd; 719*5184Sek110237 720*5184Sek110237 }| FSC_STATS FSE_DUMP whitevar_string_list 721*5184Sek110237 { 722*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 723*5184Sek110237 YYERROR; 724*5184Sek110237 725*5184Sek110237 $$->cmd_param_list = $3; 726*5184Sek110237 $$->cmd = parser_statsdump; 727*5184Sek110237 }| FSC_STATS FSE_XMLDUMP whitevar_string_list 728*5184Sek110237 { 729*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 730*5184Sek110237 YYERROR; 731*5184Sek110237 732*5184Sek110237 $$->cmd_param_list = $3; 733*5184Sek110237 $$->cmd = parser_statsxmldump; 734*5184Sek110237 }; 735*5184Sek110237 736*5184Sek110237 quit_command: FSC_QUIT 737*5184Sek110237 { 738*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 739*5184Sek110237 YYERROR; 740*5184Sek110237 $$->cmd = parser_filebench_shutdown; 741*5184Sek110237 }; 742*5184Sek110237 743*5184Sek110237 flowop_list: flowop_command 744*5184Sek110237 { 745*5184Sek110237 $$ = $1; 746*5184Sek110237 }| flowop_list flowop_command 747*5184Sek110237 { 748*5184Sek110237 cmd_t *list = NULL; 749*5184Sek110237 cmd_t *list_end = NULL; 750*5184Sek110237 751*5184Sek110237 /* Find end of list */ 752*5184Sek110237 for (list = $1; list != NULL; 753*5184Sek110237 list = list->cmd_next) 754*5184Sek110237 list_end = list; 755*5184Sek110237 756*5184Sek110237 list_end->cmd_next = $2; 757*5184Sek110237 758*5184Sek110237 filebench_log(LOG_DEBUG_IMPL, 759*5184Sek110237 "flowop_list adding cmd %zx to list %zx", $2, $1); 760*5184Sek110237 761*5184Sek110237 $$ = $1; 762*5184Sek110237 }; 763*5184Sek110237 764*5184Sek110237 thread: FSE_THREAD attr_ops FSK_OPENLST flowop_list FSK_CLOSELST 765*5184Sek110237 { 766*5184Sek110237 /* 767*5184Sek110237 * Allocate a cmd node per thread, with a 768*5184Sek110237 * list of flowops attached to the cmd_list 769*5184Sek110237 */ 770*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 771*5184Sek110237 YYERROR; 772*5184Sek110237 $$->cmd_list = $4; 773*5184Sek110237 $$->cmd_attr_list = $2; 774*5184Sek110237 }; 775*5184Sek110237 776*5184Sek110237 thread_list: thread 777*5184Sek110237 { 778*5184Sek110237 $$ = $1; 779*5184Sek110237 }| thread_list thread 780*5184Sek110237 { 781*5184Sek110237 cmd_t *list = NULL; 782*5184Sek110237 cmd_t *list_end = NULL; 783*5184Sek110237 784*5184Sek110237 /* Find end of list */ 785*5184Sek110237 for (list = $1; list != NULL; 786*5184Sek110237 list = list->cmd_next) 787*5184Sek110237 list_end = list; 788*5184Sek110237 789*5184Sek110237 list_end->cmd_next = $2; 790*5184Sek110237 791*5184Sek110237 filebench_log(LOG_DEBUG_IMPL, 792*5184Sek110237 "thread_list adding cmd %zx to list %zx", $2, $1); 793*5184Sek110237 794*5184Sek110237 $$ = $1; 795*5184Sek110237 }; 796*5184Sek110237 797*5184Sek110237 define_command: FSC_DEFINE FSE_PROC attr_ops FSK_OPENLST thread_list FSK_CLOSELST 798*5184Sek110237 { 799*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 800*5184Sek110237 YYERROR; 801*5184Sek110237 $$->cmd = &parser_proc_define; 802*5184Sek110237 $$->cmd_list = $5; 803*5184Sek110237 $$->cmd_attr_list = $3; 804*5184Sek110237 805*5184Sek110237 }| FSC_DEFINE FSE_FILE 806*5184Sek110237 { 807*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 808*5184Sek110237 YYERROR; 809*5184Sek110237 $$->cmd = &parser_file_define; 810*5184Sek110237 }| FSC_DEFINE FSE_FILESET 811*5184Sek110237 { 812*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 813*5184Sek110237 YYERROR; 814*5184Sek110237 $$->cmd = &parser_fileset_define; 815*5184Sek110237 } 816*5184Sek110237 | define_command attr_ops 817*5184Sek110237 { 818*5184Sek110237 $1->cmd_attr_list = $2; 819*5184Sek110237 }; 820*5184Sek110237 821*5184Sek110237 create_command: FSC_CREATE entity 822*5184Sek110237 { 823*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 824*5184Sek110237 YYERROR; 825*5184Sek110237 switch ($2) { 826*5184Sek110237 case FSE_PROC: 827*5184Sek110237 $$->cmd = &parser_proc_create; 828*5184Sek110237 break; 829*5184Sek110237 case FSE_FILE: 830*5184Sek110237 $$->cmd = &parser_file_create; 831*5184Sek110237 break; 832*5184Sek110237 case FSE_FILESET: 833*5184Sek110237 $$->cmd = &parser_fileset_create; 834*5184Sek110237 break; 835*5184Sek110237 default: 836*5184Sek110237 filebench_log(LOG_ERROR, "unknown entity", $2); 837*5184Sek110237 YYERROR; 838*5184Sek110237 } 839*5184Sek110237 840*5184Sek110237 }; 841*5184Sek110237 842*5184Sek110237 shutdown_command: FSC_SHUTDOWN entity 843*5184Sek110237 { 844*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 845*5184Sek110237 YYERROR; 846*5184Sek110237 switch ($2) { 847*5184Sek110237 case FSE_PROC: 848*5184Sek110237 $$->cmd = &parser_proc_shutdown; 849*5184Sek110237 break; 850*5184Sek110237 default: 851*5184Sek110237 filebench_log(LOG_ERROR, "unknown entity", $2); 852*5184Sek110237 YYERROR; 853*5184Sek110237 } 854*5184Sek110237 855*5184Sek110237 }; 856*5184Sek110237 857*5184Sek110237 sleep_command: FSC_SLEEP FSV_VAL_INT 858*5184Sek110237 { 859*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 860*5184Sek110237 YYERROR; 861*5184Sek110237 $$->cmd = parser_sleep; 862*5184Sek110237 $$->cmd_qty = $2; 863*5184Sek110237 } 864*5184Sek110237 | FSC_SLEEP FSV_VARIABLE 865*5184Sek110237 { 866*5184Sek110237 vinteger_t *integer; 867*5184Sek110237 868*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 869*5184Sek110237 YYERROR; 870*5184Sek110237 $$->cmd = parser_sleep_variable; 871*5184Sek110237 $$->cmd_tgt1 = fb_stralloc($2); 872*5184Sek110237 }; 873*5184Sek110237 874*5184Sek110237 run_command: FSC_RUN FSV_VAL_INT 875*5184Sek110237 { 876*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 877*5184Sek110237 YYERROR; 878*5184Sek110237 $$->cmd = parser_run; 879*5184Sek110237 $$->cmd_qty = $2; 880*5184Sek110237 } 881*5184Sek110237 | FSC_RUN FSV_VARIABLE 882*5184Sek110237 { 883*5184Sek110237 vinteger_t *integer; 884*5184Sek110237 885*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 886*5184Sek110237 YYERROR; 887*5184Sek110237 $$->cmd = parser_run_variable; 888*5184Sek110237 $$->cmd_tgt1 = fb_stralloc($2); 889*5184Sek110237 } 890*5184Sek110237 | FSC_RUN 891*5184Sek110237 { 892*5184Sek110237 vinteger_t *integer; 893*5184Sek110237 894*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 895*5184Sek110237 YYERROR; 896*5184Sek110237 $$->cmd = parser_run; 897*5184Sek110237 $$->cmd_qty = 60UL; 898*5184Sek110237 }; 899*5184Sek110237 900*5184Sek110237 help_command: FSC_HELP 901*5184Sek110237 { 902*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 903*5184Sek110237 YYERROR; 904*5184Sek110237 $$->cmd = parser_help; 905*5184Sek110237 }; 906*5184Sek110237 907*5184Sek110237 flowop_command: FSC_FLOWOP name 908*5184Sek110237 { 909*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 910*5184Sek110237 YYERROR; 911*5184Sek110237 $$->cmd_name = fb_stralloc($2); 912*5184Sek110237 } 913*5184Sek110237 | flowop_command attr_ops 914*5184Sek110237 { 915*5184Sek110237 $1->cmd_attr_list = $2; 916*5184Sek110237 }; 917*5184Sek110237 918*5184Sek110237 load_command: FSC_LOAD FSV_STRING 919*5184Sek110237 { 920*5184Sek110237 FILE *newfile; 921*5184Sek110237 char loadfile[128]; 922*5184Sek110237 923*5184Sek110237 if (($$ = alloc_cmd()) == NULL) 924*5184Sek110237 YYERROR; 925*5184Sek110237 926*5184Sek110237 (void) strcpy(loadfile, $2); 927*5184Sek110237 (void) strcat(loadfile, ".f"); 928*5184Sek110237 929*5184Sek110237 if ((newfile = fopen(loadfile, "r")) == NULL) { 930*5184Sek110237 (void) strcpy(loadfile, FILEBENCHDIR); 931*5184Sek110237 (void) strcat(loadfile, "/workloads/"); 932*5184Sek110237 (void) strcat(loadfile, $2); 933*5184Sek110237 (void) strcat(loadfile, ".f"); 934*5184Sek110237 if ((newfile = fopen(loadfile, "r")) == NULL) { 935*5184Sek110237 filebench_log(LOG_ERROR, "Cannot open %s", loadfile); 936*5184Sek110237 YYERROR; 937*5184Sek110237 } 938*5184Sek110237 } 939*5184Sek110237 940*5184Sek110237 parentscript = yyin; 941*5184Sek110237 yyin = newfile; 942*5184Sek110237 yy_switchfileparent(yyin); 943*5184Sek110237 }; 944*5184Sek110237 945*5184Sek110237 entity: FSE_PROC {$$ = FSE_PROC;} 946*5184Sek110237 | FSE_THREAD {$$ = FSE_THREAD;} 947*5184Sek110237 | FSE_FILESET {$$ = FSE_FILESET;} 948*5184Sek110237 | FSE_FILE {$$ = FSE_FILE;}; 949*5184Sek110237 950*5184Sek110237 value: FSV_VAL_INT { $$.i = $1;} 951*5184Sek110237 | FSV_STRING { $$.s = $1;} 952*5184Sek110237 | FSV_VAL_BOOLEAN { $$.b = $1;}; 953*5184Sek110237 954*5184Sek110237 name: FSV_STRING; 955*5184Sek110237 956*5184Sek110237 attr_ops: attr_op 957*5184Sek110237 { 958*5184Sek110237 $$ = $1; 959*5184Sek110237 } 960*5184Sek110237 | attr_ops FSK_SEPLST attr_op 961*5184Sek110237 { 962*5184Sek110237 attr_t *attr = NULL; 963*5184Sek110237 attr_t *list_end = NULL; 964*5184Sek110237 965*5184Sek110237 for (attr = $1; attr != NULL; 966*5184Sek110237 attr = attr->attr_next) 967*5184Sek110237 list_end = attr; /* Find end of list */ 968*5184Sek110237 969*5184Sek110237 list_end->attr_next = $3; 970*5184Sek110237 971*5184Sek110237 $$ = $1; 972*5184Sek110237 }; 973*5184Sek110237 974*5184Sek110237 attr_op: attr_name FSK_ASSIGN attr_value 975*5184Sek110237 { 976*5184Sek110237 $$ = $3; 977*5184Sek110237 $$->attr_name = $1; 978*5184Sek110237 } 979*5184Sek110237 | attr_name 980*5184Sek110237 { 981*5184Sek110237 if (($$ = alloc_attr()) == NULL) 982*5184Sek110237 YYERROR; 983*5184Sek110237 $$->attr_name = $1; 984*5184Sek110237 } 985*5184Sek110237 986*5184Sek110237 attr_name: attrs_define_file 987*5184Sek110237 |attrs_define_fileset 988*5184Sek110237 |attrs_define_thread 989*5184Sek110237 |attrs_define_proc 990*5184Sek110237 |attrs_flowop 991*5184Sek110237 |attrs_eventgen; 992*5184Sek110237 993*5184Sek110237 attrs_define_proc: 994*5184Sek110237 FSA_NICE { $$ = FSA_NICE;} 995*5184Sek110237 |FSA_INSTANCES { $$ = FSA_INSTANCES;}; 996*5184Sek110237 997*5184Sek110237 attrs_define_file: 998*5184Sek110237 FSA_SIZE { $$ = FSA_SIZE;} 999*5184Sek110237 | FSA_PATH { $$ = FSA_PATH;} 1000*5184Sek110237 | FSA_REUSE { $$ = FSA_REUSE;} 1001*5184Sek110237 | FSA_PREALLOC { $$ = FSA_PREALLOC;} 1002*5184Sek110237 | FSA_PARALLOC { $$ = FSA_PARALLOC;}; 1003*5184Sek110237 1004*5184Sek110237 attrs_define_fileset: 1005*5184Sek110237 FSA_SIZE { $$ = FSA_SIZE;} 1006*5184Sek110237 | FSA_PATH { $$ = FSA_PATH;} 1007*5184Sek110237 | FSA_DIRWIDTH { $$ = FSA_DIRWIDTH;} 1008*5184Sek110237 | FSA_PREALLOC { $$ = FSA_PREALLOC;} 1009*5184Sek110237 | FSA_FILESIZEGAMMA { $$ = FSA_FILESIZEGAMMA;} 1010*5184Sek110237 | FSA_DIRGAMMA { $$ = FSA_DIRGAMMA;} 1011*5184Sek110237 | FSA_CACHED { $$ = FSA_CACHED;} 1012*5184Sek110237 | FSA_ENTRIES { $$ = FSA_ENTRIES;}; 1013*5184Sek110237 1014*5184Sek110237 attrs_define_thread: 1015*5184Sek110237 FSA_PROCESS { $$ = FSA_PROCESS;} 1016*5184Sek110237 |FSA_MEMSIZE { $$ = FSA_MEMSIZE;} 1017*5184Sek110237 |FSA_USEISM { $$ = FSA_USEISM;} 1018*5184Sek110237 |FSA_INSTANCES { $$ = FSA_INSTANCES;}; 1019*5184Sek110237 1020*5184Sek110237 attrs_flowop: 1021*5184Sek110237 FSA_WSS { $$ = FSA_WSS;} 1022*5184Sek110237 |FSA_FILE { $$ = FSA_FILE;} 1023*5184Sek110237 |FSA_NAME { $$ = FSA_NAME;} 1024*5184Sek110237 |FSA_RANDOM { $$ = FSA_RANDOM;} 1025*5184Sek110237 |FSA_FD { $$ = FSA_FD;} 1026*5184Sek110237 |FSA_SRCFD { $$ = FSA_SRCFD;} 1027*5184Sek110237 |FSA_ROTATEFD { $$ = FSA_ROTATEFD;} 1028*5184Sek110237 |FSA_DSYNC { $$ = FSA_DSYNC;} 1029*5184Sek110237 |FSA_DIRECTIO { $$ = FSA_DIRECTIO;} 1030*5184Sek110237 |FSA_TARGET { $$ = FSA_TARGET;} 1031*5184Sek110237 |FSA_ITERS { $$ = FSA_ITERS;} 1032*5184Sek110237 |FSA_VALUE { $$ = FSA_VALUE;} 1033*5184Sek110237 |FSA_BLOCKING { $$ = FSA_BLOCKING;} 1034*5184Sek110237 |FSA_HIGHWATER { $$ = FSA_HIGHWATER;} 1035*5184Sek110237 |FSA_IOSIZE { $$ = FSA_IOSIZE;}; 1036*5184Sek110237 1037*5184Sek110237 attrs_eventgen: 1038*5184Sek110237 FSA_RATE { $$ = FSA_RATE;}; 1039*5184Sek110237 1040*5184Sek110237 attr_value: var_string_list { 1041*5184Sek110237 if (($$ = alloc_attr()) == NULL) 1042*5184Sek110237 YYERROR; 1043*5184Sek110237 $$->attr_param_list = $1; 1044*5184Sek110237 } | FSV_STRING 1045*5184Sek110237 { 1046*5184Sek110237 if (($$ = alloc_attr()) == NULL) 1047*5184Sek110237 YYERROR; 1048*5184Sek110237 $$->attr_string = string_alloc($1); 1049*5184Sek110237 } | FSV_VAL_INT { 1050*5184Sek110237 if (($$ = alloc_attr()) == NULL) 1051*5184Sek110237 YYERROR; 1052*5184Sek110237 $$->attr_integer = integer_alloc($1); 1053*5184Sek110237 } | FSV_VARIABLE { 1054*5184Sek110237 if (($$ = alloc_attr()) == NULL) 1055*5184Sek110237 YYERROR; 1056*5184Sek110237 $$->attr_integer = var_ref_integer($1); 1057*5184Sek110237 $$->attr_string = var_ref_string($1); 1058*5184Sek110237 }; 1059*5184Sek110237 1060*5184Sek110237 %% 1061*5184Sek110237 1062*5184Sek110237 /* 1063*5184Sek110237 * The following 'c' routines implement the various commands defined in the 1064*5184Sek110237 * above yacc parser code. The yacc portion checks the syntax of the commands 1065*5184Sek110237 * found in a workload file, or typed on interactive command lines, parsing 1066*5184Sek110237 * the commands' parameters into lists. The lists are then passed in a cmd_t 1067*5184Sek110237 * struct for each command to its related routine in the following section 1068*5184Sek110237 * for actual execution. This section also includes a few utility routines 1069*5184Sek110237 * and the main entry point for the program. 1070*5184Sek110237 */ 1071*5184Sek110237 1072*5184Sek110237 /* 1073*5184Sek110237 * Entry point for filebench. Processes command line arguements. The -f 1074*5184Sek110237 * option will read in a workload file (the full name and extension must 1075*5184Sek110237 * must be given). The -a, -s, -m and -i options are used by worker process 1076*5184Sek110237 * to receive their name, the base address of shared memory, its path, and 1077*5184Sek110237 * the process' instance number, respectively. This information is supplied 1078*5184Sek110237 * by the master process when it execs worker processes under the process 1079*5184Sek110237 * model of execution. If the worker process arguments are passed then main 1080*5184Sek110237 * will call the procflow_exec routine which creates worker threadflows and 1081*5184Sek110237 * flowops and executes the procflow's portion of the workload model until 1082*5184Sek110237 * completion. If worker process arguments are not passed to the process, 1083*5184Sek110237 * then it becomes the master process for a filebench run. It initializes 1084*5184Sek110237 * the various filebench components and either executes the supplied workload 1085*5184Sek110237 * file, or enters interactive mode. 1086*5184Sek110237 */ 1087*5184Sek110237 1088*5184Sek110237 int 1089*5184Sek110237 main(int argc, char *argv[]) 1090*5184Sek110237 { 1091*5184Sek110237 int opt; 1092*5184Sek110237 int docmd = FS_FALSE; 1093*5184Sek110237 int instance; 1094*5184Sek110237 char procname[128]; 1095*5184Sek110237 caddr_t shmaddr; 1096*5184Sek110237 char dir[MAXPATHLEN]; 1097*5184Sek110237 #ifdef HAVE_SETRLIMIT 1098*5184Sek110237 struct rlimit rlp; 1099*5184Sek110237 #endif 1100*5184Sek110237 #ifdef HAVE_LIBTECLA 1101*5184Sek110237 char *line; 1102*5184Sek110237 #else 1103*5184Sek110237 char line[1024]; 1104*5184Sek110237 #endif 1105*5184Sek110237 char shmpathtmp[1024]; 1106*5184Sek110237 1107*5184Sek110237 #ifdef HAVE_SETRLIMIT 1108*5184Sek110237 /* Set resource limits */ 1109*5184Sek110237 (void) getrlimit(RLIMIT_NOFILE, &rlp); 1110*5184Sek110237 rlp.rlim_cur = rlp.rlim_max; 1111*5184Sek110237 setrlimit(RLIMIT_NOFILE, &rlp); 1112*5184Sek110237 #endif 1113*5184Sek110237 1114*5184Sek110237 yydebug = 0; 1115*5184Sek110237 execname = argv[0]; 1116*5184Sek110237 *procname = 0; 1117*5184Sek110237 cwd = getcwd(dir, MAXPATHLEN); 1118*5184Sek110237 1119*5184Sek110237 while ((opt = getopt(argc, argv, cmd_options)) != (int)EOF) { 1120*5184Sek110237 1121*5184Sek110237 switch (opt) { 1122*5184Sek110237 case 'h': 1123*5184Sek110237 usage(2); 1124*5184Sek110237 break; 1125*5184Sek110237 1126*5184Sek110237 case 'p': 1127*5184Sek110237 noproc = 1; 1128*5184Sek110237 break; 1129*5184Sek110237 1130*5184Sek110237 case 'f': 1131*5184Sek110237 if (optarg == NULL) 1132*5184Sek110237 usage(1); 1133*5184Sek110237 if ((yyin = fopen(optarg, "r")) == NULL) { 1134*5184Sek110237 (void) fprintf(stderr, 1135*5184Sek110237 "Cannot open file %s", optarg); 1136*5184Sek110237 exit(1); 1137*5184Sek110237 } 1138*5184Sek110237 dofile = FS_TRUE; 1139*5184Sek110237 fscriptname = optarg; 1140*5184Sek110237 1141*5184Sek110237 break; 1142*5184Sek110237 1143*5184Sek110237 case 'a': 1144*5184Sek110237 if (optarg == NULL) 1145*5184Sek110237 usage(1); 1146*5184Sek110237 sscanf(optarg, "%s", &procname[0]); 1147*5184Sek110237 break; 1148*5184Sek110237 1149*5184Sek110237 case 's': 1150*5184Sek110237 if (optarg == NULL) 1151*5184Sek110237 usage(1); 1152*5184Sek110237 #if defined(_LP64) || (__WORDSIZE == 64) 1153*5184Sek110237 sscanf(optarg, "%llx", &shmaddr); 1154*5184Sek110237 #else 1155*5184Sek110237 sscanf(optarg, "%x", &shmaddr); 1156*5184Sek110237 #endif 1157*5184Sek110237 break; 1158*5184Sek110237 1159*5184Sek110237 case 'm': 1160*5184Sek110237 if (optarg == NULL) 1161*5184Sek110237 usage(1); 1162*5184Sek110237 sscanf(optarg, "%s", shmpathtmp); 1163*5184Sek110237 shmpath = shmpathtmp; 1164*5184Sek110237 break; 1165*5184Sek110237 1166*5184Sek110237 case 'i': 1167*5184Sek110237 if (optarg == NULL) 1168*5184Sek110237 usage(1); 1169*5184Sek110237 sscanf(optarg, "%d", &instance); 1170*5184Sek110237 break; 1171*5184Sek110237 1172*5184Sek110237 case '?': 1173*5184Sek110237 default: 1174*5184Sek110237 usage(1); 1175*5184Sek110237 break; 1176*5184Sek110237 } 1177*5184Sek110237 } 1178*5184Sek110237 1179*5184Sek110237 #ifdef USE_PROCESS_MODEL 1180*5184Sek110237 if (!(*procname)) 1181*5184Sek110237 #endif 1182*5184Sek110237 printf("FileBench Version %s\n", FILEBENCH_VERSION); 1183*5184Sek110237 filebench_init(); 1184*5184Sek110237 1185*5184Sek110237 #ifdef USE_PROCESS_MODEL 1186*5184Sek110237 if (*procname) { 1187*5184Sek110237 pid = getpid(); 1188*5184Sek110237 1189*5184Sek110237 if (ipc_attach(shmaddr) < 0) { 1190*5184Sek110237 filebench_log(LOG_ERROR, "Cannot attach shm for %s", 1191*5184Sek110237 procname); 1192*5184Sek110237 exit(1); 1193*5184Sek110237 } 1194*5184Sek110237 1195*5184Sek110237 if (procflow_exec(procname, instance) < 0) { 1196*5184Sek110237 filebench_log(LOG_ERROR, "Cannot startup process %s", 1197*5184Sek110237 procname); 1198*5184Sek110237 exit(1); 1199*5184Sek110237 } 1200*5184Sek110237 exit(1); 1201*5184Sek110237 } 1202*5184Sek110237 #endif 1203*5184Sek110237 1204*5184Sek110237 pid = getpid(); 1205*5184Sek110237 ipc_init(); 1206*5184Sek110237 1207*5184Sek110237 if (fscriptname) 1208*5184Sek110237 (void) strcpy(filebench_shm->fscriptname, fscriptname); 1209*5184Sek110237 1210*5184Sek110237 flowop_init(); 1211*5184Sek110237 stats_init(); 1212*5184Sek110237 eventgen_init(); 1213*5184Sek110237 1214*5184Sek110237 signal(SIGINT, parser_abort); 1215*5184Sek110237 1216*5184Sek110237 if (dofile) 1217*5184Sek110237 yyparse(); 1218*5184Sek110237 else { 1219*5184Sek110237 #ifdef HAVE_LIBTECLA 1220*5184Sek110237 if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL) { 1221*5184Sek110237 filebench_log(LOG_ERROR, 1222*5184Sek110237 "Failed to create GetLine object"); 1223*5184Sek110237 filebench_shutdown(1); 1224*5184Sek110237 } 1225*5184Sek110237 1226*5184Sek110237 if (gl_customize_completion(gl, NULL, command_complete)) { 1227*5184Sek110237 filebench_log(LOG_ERROR, 1228*5184Sek110237 "Failed to register auto-completion function"); 1229*5184Sek110237 filebench_shutdown(1); 1230*5184Sek110237 } 1231*5184Sek110237 1232*5184Sek110237 while (line = gl_get_line(gl, FILEBENCH_PROMPT, NULL, -1)) { 1233*5184Sek110237 arg_parse(line); 1234*5184Sek110237 yyparse(); 1235*5184Sek110237 } 1236*5184Sek110237 1237*5184Sek110237 del_GetLine(gl); 1238*5184Sek110237 #else 1239*5184Sek110237 while (!feof(stdin)) { 1240*5184Sek110237 printf(FILEBENCH_PROMPT); 1241*5184Sek110237 fflush(stdout); 1242*5184Sek110237 if (fgets(line, sizeof (line), stdin) == NULL) { 1243*5184Sek110237 if (errno == EINTR) 1244*5184Sek110237 continue; 1245*5184Sek110237 else 1246*5184Sek110237 break; 1247*5184Sek110237 } 1248*5184Sek110237 arg_parse(line); 1249*5184Sek110237 yyparse(); 1250*5184Sek110237 } 1251*5184Sek110237 printf("\n"); 1252*5184Sek110237 #endif /* HAVE_LIBTECLA */ 1253*5184Sek110237 } 1254*5184Sek110237 1255*5184Sek110237 parser_filebench_shutdown((cmd_t *)0); 1256*5184Sek110237 1257*5184Sek110237 return (0); 1258*5184Sek110237 } 1259*5184Sek110237 1260*5184Sek110237 /* 1261*5184Sek110237 * arg_parse() puts the parser into command parsing mode. Create a tmpfile 1262*5184Sek110237 * and instruct the parser to read instructions from this location by setting 1263*5184Sek110237 * yyin to the value returned by tmpfile. Write the command into the file. 1264*5184Sek110237 * Then seek back to to the start of the file so that the parser can read 1265*5184Sek110237 * the instructions. 1266*5184Sek110237 */ 1267*5184Sek110237 static void 1268*5184Sek110237 arg_parse(const char *command) 1269*5184Sek110237 { 1270*5184Sek110237 if ((yyin = tmpfile()) == NULL) 1271*5184Sek110237 filebench_log(LOG_FATAL, 1272*5184Sek110237 "Cannot create tmpfile: %s", strerror(errno)); 1273*5184Sek110237 1274*5184Sek110237 if (fwrite(command, strlen(command), 1, yyin) != 1) 1275*5184Sek110237 filebench_log(LOG_FATAL, 1276*5184Sek110237 "Cannot write tmpfile: %s", strerror(errno)); 1277*5184Sek110237 1278*5184Sek110237 if (fseek(yyin, 0, SEEK_SET) != 0) 1279*5184Sek110237 filebench_log(LOG_FATAL, 1280*5184Sek110237 "Cannot seek tmpfile: %s", strerror(errno)); 1281*5184Sek110237 } 1282*5184Sek110237 1283*5184Sek110237 /* 1284*5184Sek110237 * Converts a list of var_strings or ordinary strings to a single ordinary 1285*5184Sek110237 * string. It returns a pointer to the string (in malloc'd memory) if found, 1286*5184Sek110237 * or NULL otherwise. 1287*5184Sek110237 */ 1288*5184Sek110237 char * 1289*5184Sek110237 parser_list2string(list_t *list) 1290*5184Sek110237 { 1291*5184Sek110237 list_t *l; 1292*5184Sek110237 char *string; 1293*5184Sek110237 char *tmp; 1294*5184Sek110237 vinteger_t *integer; 1295*5184Sek110237 1296*5184Sek110237 if ((string = malloc(MAXPATHLEN)) == NULL) { 1297*5184Sek110237 filebench_log(LOG_ERROR, "Failed to allocate memory"); 1298*5184Sek110237 return (NULL); 1299*5184Sek110237 } 1300*5184Sek110237 1301*5184Sek110237 *string = 0; 1302*5184Sek110237 1303*5184Sek110237 1304*5184Sek110237 /* Format args */ 1305*5184Sek110237 for (l = list; l != NULL; 1306*5184Sek110237 l = l->list_next) { 1307*5184Sek110237 filebench_log(LOG_DEBUG_SCRIPT, 1308*5184Sek110237 "converting string '%s'", *l->list_string); 1309*5184Sek110237 1310*5184Sek110237 if ((tmp = var_to_string(*l->list_string)) != NULL) { 1311*5184Sek110237 (void) strcat(string, tmp); 1312*5184Sek110237 free(tmp); 1313*5184Sek110237 } else { 1314*5184Sek110237 (void) strcat(string, *l->list_string); 1315*5184Sek110237 } 1316*5184Sek110237 } 1317*5184Sek110237 return (string); 1318*5184Sek110237 } 1319*5184Sek110237 1320*5184Sek110237 /* 1321*5184Sek110237 * If the list just contains a single string starting with '$', then find 1322*5184Sek110237 * or create the named var and return the var's var_string component. 1323*5184Sek110237 * Otherwise, convert the list to a string, and allocate a var_string 1324*5184Sek110237 * containing a copy of that string. On failure either returns NULL 1325*5184Sek110237 * or shuts down the run. 1326*5184Sek110237 */ 1327*5184Sek110237 var_string_t 1328*5184Sek110237 parser_list2varstring(list_t *list) 1329*5184Sek110237 { 1330*5184Sek110237 /* Special case - variable name */ 1331*5184Sek110237 if ((list->list_next == NULL) && (*(*list->list_string) == '$')) 1332*5184Sek110237 return (var_ref_string(*list->list_string)); 1333*5184Sek110237 1334*5184Sek110237 return (string_alloc(parser_list2string(list))); 1335*5184Sek110237 } 1336*5184Sek110237 1337*5184Sek110237 /* 1338*5184Sek110237 * Looks for the var named in list_string of the first element of the 1339*5184Sek110237 * supplied list. If found, returns the var_integer portion of the var. 1340*5184Sek110237 * If the var is not found, cannot be allocated, the supplied list is 1341*5184Sek110237 * NULL, or the list_string filed is empty, returns NULL. 1342*5184Sek110237 */ 1343*5184Sek110237 var_integer_t 1344*5184Sek110237 parser_list2integer(list_t *list) 1345*5184Sek110237 { 1346*5184Sek110237 var_integer_t v; 1347*5184Sek110237 1348*5184Sek110237 if (list && (*(list->list_string) != NULL)) { 1349*5184Sek110237 v = var_ref_integer(*(list->list_string)); 1350*5184Sek110237 return (v); 1351*5184Sek110237 } 1352*5184Sek110237 1353*5184Sek110237 return (NULL); 1354*5184Sek110237 } 1355*5184Sek110237 1356*5184Sek110237 /* 1357*5184Sek110237 * Sets the event generator rate from the attribute supplied with the 1358*5184Sek110237 * command. If the attribute doesn't exist the routine does nothing. 1359*5184Sek110237 */ 1360*5184Sek110237 static void 1361*5184Sek110237 parser_eventgen(cmd_t *cmd) 1362*5184Sek110237 { 1363*5184Sek110237 attr_t *attr; 1364*5184Sek110237 vinteger_t rate; 1365*5184Sek110237 1366*5184Sek110237 /* Get the rate from attribute */ 1367*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_RATE)) { 1368*5184Sek110237 if (attr->attr_integer) { 1369*5184Sek110237 filebench_log(LOG_VERBOSE, 1370*5184Sek110237 "Eventgen: %lld per second", 1371*5184Sek110237 *attr->attr_integer); 1372*5184Sek110237 eventgen_setrate(*attr->attr_integer); 1373*5184Sek110237 } 1374*5184Sek110237 } 1375*5184Sek110237 1376*5184Sek110237 } 1377*5184Sek110237 1378*5184Sek110237 /* 1379*5184Sek110237 * Assigns the designated integer variable successive values from the 1380*5184Sek110237 * supplied comma seperated integer list. After each successive integer 1381*5184Sek110237 * assignment, it executes the bracket enclosed list of commands. For 1382*5184Sek110237 * example, repeated runs of a workload with increasing io sizes can 1383*5184Sek110237 * be done using the following command line: 1384*5184Sek110237 * foreach $iosize in 2k, 4k, 8k {run 60} 1385*5184Sek110237 */ 1386*5184Sek110237 static void 1387*5184Sek110237 parser_foreach_integer(cmd_t *cmd) 1388*5184Sek110237 { 1389*5184Sek110237 list_t *list = cmd->cmd_param_list; 1390*5184Sek110237 cmd_t *inner_cmd; 1391*5184Sek110237 1392*5184Sek110237 for (; list != NULL; list = list->list_next) { 1393*5184Sek110237 var_assign_integer(cmd->cmd_tgt1, *list->list_integer); 1394*5184Sek110237 filebench_log(LOG_VERBOSE, "Iterating %s=%lld", 1395*5184Sek110237 cmd->cmd_tgt1, 1396*5184Sek110237 *list->list_integer); 1397*5184Sek110237 for (inner_cmd = cmd->cmd_list; inner_cmd != NULL; 1398*5184Sek110237 inner_cmd = inner_cmd->cmd_next) { 1399*5184Sek110237 inner_cmd->cmd(inner_cmd); 1400*5184Sek110237 } 1401*5184Sek110237 } 1402*5184Sek110237 } 1403*5184Sek110237 1404*5184Sek110237 /* 1405*5184Sek110237 * Similar to parser_foreach_integer(), except takes a list of strings after 1406*5184Sek110237 * the "in" token. For example, to run twice using a different directory, 1407*5184Sek110237 * perhaps using a different filesystem, the following command line 1408*5184Sek110237 * could be used: 1409*5184Sek110237 * foreach $dir in "/ufs_top/fbt", "/zfs_top/fbt" {run 60) 1410*5184Sek110237 */ 1411*5184Sek110237 static void 1412*5184Sek110237 parser_foreach_string(cmd_t *cmd) 1413*5184Sek110237 { 1414*5184Sek110237 list_t *list = cmd->cmd_param_list; 1415*5184Sek110237 cmd_t *inner_cmd; 1416*5184Sek110237 1417*5184Sek110237 for (; list != NULL; list = list->list_next) { 1418*5184Sek110237 var_assign_string(cmd->cmd_tgt1, *list->list_string); 1419*5184Sek110237 filebench_log(LOG_VERBOSE, "Iterating %s=%s", 1420*5184Sek110237 cmd->cmd_tgt1, 1421*5184Sek110237 *list->list_string); 1422*5184Sek110237 for (inner_cmd = cmd->cmd_list; inner_cmd != NULL; 1423*5184Sek110237 inner_cmd = inner_cmd->cmd_next) { 1424*5184Sek110237 inner_cmd->cmd(inner_cmd); 1425*5184Sek110237 } 1426*5184Sek110237 } 1427*5184Sek110237 } 1428*5184Sek110237 1429*5184Sek110237 /* 1430*5184Sek110237 * Lists the file name, path name and file size for all defined file objects. 1431*5184Sek110237 */ 1432*5184Sek110237 static void 1433*5184Sek110237 parser_list(cmd_t *cmd) 1434*5184Sek110237 { 1435*5184Sek110237 (void) fileobj_iter(fileobj_print); 1436*5184Sek110237 } 1437*5184Sek110237 1438*5184Sek110237 /* 1439*5184Sek110237 * Calls procflow_define() to allocate "instances" number of procflow(s) 1440*5184Sek110237 * (processes) with the supplied name. The default number of instances is 1441*5184Sek110237 * one. An optional priority level attribute can be supplied and is stored in 1442*5184Sek110237 * pf_nice. Finally the routine loops through the list of inner commands, if 1443*5184Sek110237 * any, which are defines for threadflows, and passes them one at a time to 1444*5184Sek110237 * parser_thread_define() to allocate threadflow entities for the process(es). 1445*5184Sek110237 */ 1446*5184Sek110237 static void 1447*5184Sek110237 parser_proc_define(cmd_t *cmd) 1448*5184Sek110237 { 1449*5184Sek110237 procflow_t *procflow, template; 1450*5184Sek110237 char *name; 1451*5184Sek110237 attr_t *attr; 1452*5184Sek110237 var_integer_t instances = integer_alloc(1); 1453*5184Sek110237 cmd_t *inner_cmd; 1454*5184Sek110237 1455*5184Sek110237 /* Get the name of the process */ 1456*5184Sek110237 if (attr = get_attr(cmd, FSA_NAME)) { 1457*5184Sek110237 name = *attr->attr_string; 1458*5184Sek110237 } else { 1459*5184Sek110237 filebench_log(LOG_ERROR, 1460*5184Sek110237 "define proc: proc specifies no name"); 1461*5184Sek110237 filebench_shutdown(1); 1462*5184Sek110237 } 1463*5184Sek110237 1464*5184Sek110237 /* Get the memory size from attribute */ 1465*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_INSTANCES)) { 1466*5184Sek110237 filebench_log(LOG_DEBUG_IMPL, 1467*5184Sek110237 "Setting instances = %lld", 1468*5184Sek110237 *attr->attr_integer); 1469*5184Sek110237 instances = attr->attr_integer; 1470*5184Sek110237 } 1471*5184Sek110237 1472*5184Sek110237 if ((procflow = procflow_define(name, NULL, instances)) == NULL) { 1473*5184Sek110237 filebench_log(LOG_ERROR, 1474*5184Sek110237 "Failed to instantiate %d %s process(es)\n", 1475*5184Sek110237 instances, name); 1476*5184Sek110237 filebench_shutdown(1); 1477*5184Sek110237 } 1478*5184Sek110237 1479*5184Sek110237 /* Get the pri from attribute */ 1480*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_NICE)) { 1481*5184Sek110237 filebench_log(LOG_DEBUG_IMPL, "Setting pri = %lld", 1482*5184Sek110237 *attr->attr_integer); 1483*5184Sek110237 procflow->pf_nice = attr->attr_integer; 1484*5184Sek110237 } else 1485*5184Sek110237 procflow->pf_nice = integer_alloc(0); 1486*5184Sek110237 1487*5184Sek110237 1488*5184Sek110237 /* Create the list of threads for this process */ 1489*5184Sek110237 for (inner_cmd = cmd->cmd_list; inner_cmd != NULL; 1490*5184Sek110237 inner_cmd = inner_cmd->cmd_next) { 1491*5184Sek110237 parser_thread_define(inner_cmd, procflow, *instances); 1492*5184Sek110237 } 1493*5184Sek110237 } 1494*5184Sek110237 1495*5184Sek110237 /* 1496*5184Sek110237 * Calls threadflow_define() to allocate "instances" number of threadflow(s) 1497*5184Sek110237 * (threads) with the supplied name. The default number of instances is 1498*5184Sek110237 * one. Two other optional attributes may be supplied, one to set the memory 1499*5184Sek110237 * size, stored in tf_memsize, and to select the use of Interprocess Shared 1500*5184Sek110237 * Memory, which sets the THREADFLOW_USEISM flag in tf_attrs. Finally 1501*5184Sek110237 * the routine loops through the list of inner commands, if any, which are 1502*5184Sek110237 * defines for flowops, and passes them one at a time to 1503*5184Sek110237 * parser_flowop_define() to allocate flowop entities for the threadflows. 1504*5184Sek110237 */ 1505*5184Sek110237 static void 1506*5184Sek110237 parser_thread_define(cmd_t *cmd, procflow_t *procflow, int procinstances) 1507*5184Sek110237 { 1508*5184Sek110237 threadflow_t *threadflow, template; 1509*5184Sek110237 attr_t *attr; 1510*5184Sek110237 var_integer_t instances = integer_alloc(1); 1511*5184Sek110237 cmd_t *inner_cmd; 1512*5184Sek110237 char *name; 1513*5184Sek110237 1514*5184Sek110237 memset(&template, 0, sizeof (threadflow_t)); 1515*5184Sek110237 1516*5184Sek110237 /* Get the name of the thread */ 1517*5184Sek110237 if (attr = get_attr(cmd, FSA_NAME)) { 1518*5184Sek110237 name = *attr->attr_string; 1519*5184Sek110237 } else { 1520*5184Sek110237 filebench_log(LOG_ERROR, 1521*5184Sek110237 "define thread: thread in process %s specifies no name", 1522*5184Sek110237 procflow->pf_name); 1523*5184Sek110237 filebench_shutdown(1); 1524*5184Sek110237 } 1525*5184Sek110237 1526*5184Sek110237 /* Get the number of instances from attribute */ 1527*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_INSTANCES)) { 1528*5184Sek110237 filebench_log(LOG_DEBUG_IMPL, 1529*5184Sek110237 "define thread: Setting instances = %lld", 1530*5184Sek110237 *attr->attr_integer); 1531*5184Sek110237 instances = attr->attr_integer; 1532*5184Sek110237 } 1533*5184Sek110237 1534*5184Sek110237 /* Get the memory size from attribute */ 1535*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_MEMSIZE)) { 1536*5184Sek110237 filebench_log(LOG_DEBUG_IMPL, 1537*5184Sek110237 "define thread: Setting memsize = %lld", 1538*5184Sek110237 *attr->attr_integer); 1539*5184Sek110237 template.tf_memsize = attr->attr_integer; 1540*5184Sek110237 } else 1541*5184Sek110237 template.tf_memsize = integer_alloc(0); 1542*5184Sek110237 1543*5184Sek110237 if ((threadflow = threadflow_define(procflow, name, 1544*5184Sek110237 &template, instances)) == NULL) { 1545*5184Sek110237 filebench_log(LOG_ERROR, 1546*5184Sek110237 "define thread: Failed to instantiate thread\n"); 1547*5184Sek110237 filebench_shutdown(1); 1548*5184Sek110237 } 1549*5184Sek110237 1550*5184Sek110237 /* Use ISM Memory? */ 1551*5184Sek110237 if (attr = get_attr(cmd, FSA_USEISM)) { 1552*5184Sek110237 threadflow->tf_attrs |= THREADFLOW_USEISM; 1553*5184Sek110237 } 1554*5184Sek110237 1555*5184Sek110237 /* Create the list of flowops */ 1556*5184Sek110237 for (inner_cmd = cmd->cmd_list; inner_cmd != NULL; 1557*5184Sek110237 inner_cmd = inner_cmd->cmd_next) { 1558*5184Sek110237 parser_flowop_define(inner_cmd, threadflow); 1559*5184Sek110237 } 1560*5184Sek110237 } 1561*5184Sek110237 1562*5184Sek110237 /* 1563*5184Sek110237 * Calls flowop_define() to allocate a flowop with the supplied name. 1564*5184Sek110237 * The allocated flowop inherits attributes from a base flowop of the 1565*5184Sek110237 * same type. If the new flowop has a file or fileset attribute specified, 1566*5184Sek110237 * it must specify a defined fileobj or fileset or an error will be logged. 1567*5184Sek110237 * The new flowop may also have the following attributes set by 1568*5184Sek110237 * the program: 1569*5184Sek110237 * - file size (fo_iosize) 1570*5184Sek110237 * - working set size (fo_wss) 1571*5184Sek110237 * - do random io (fo_random) 1572*5184Sek110237 * - do synchronous io (fo_dsync) 1573*5184Sek110237 * - perform each operation multiple times before advancing (fo_iter) 1574*5184Sek110237 * - target name (fo_targetname) 1575*5184Sek110237 * - An integer value (fo_value) 1576*5184Sek110237 * - a file descriptor (fo_fd) 1577*5184Sek110237 * - specify to rotate file descriptors (fo_rotatefd) 1578*5184Sek110237 * - a source fd (fo_srcfdnumber) 1579*5184Sek110237 * - specify a blocking operation (fo_blocking) 1580*5184Sek110237 * - specify a highwater mark (fo_highwater) 1581*5184Sek110237 * 1582*5184Sek110237 * After all the supplied attributes are stored in their respective locations 1583*5184Sek110237 * in the flowop object, the flowop's init function is called. No errors are 1584*5184Sek110237 * returned, but the filebench run will be terminated if the flowtype is not 1585*5184Sek110237 * specified, a name for the new flowop is not supplied, the flowop_define 1586*5184Sek110237 * call fails, or a file or fileset name is supplied but the corresponding 1587*5184Sek110237 * fileobj or fileset cannot be located. 1588*5184Sek110237 */ 1589*5184Sek110237 static void 1590*5184Sek110237 parser_flowop_define(cmd_t *cmd, threadflow_t *thread) 1591*5184Sek110237 { 1592*5184Sek110237 flowop_t *flowop, *flowop_type; 1593*5184Sek110237 fileobj_t *fileobj; 1594*5184Sek110237 char *type = (char *)cmd->cmd_name; 1595*5184Sek110237 char *name; 1596*5184Sek110237 attr_t *attr; 1597*5184Sek110237 1598*5184Sek110237 /* Get the inherited flowop */ 1599*5184Sek110237 flowop_type = flowop_find(type); 1600*5184Sek110237 if (flowop_type == NULL) { 1601*5184Sek110237 filebench_log(LOG_ERROR, 1602*5184Sek110237 "define flowop: flowop type %s not found", 1603*5184Sek110237 type); 1604*5184Sek110237 filebench_shutdown(1); 1605*5184Sek110237 } 1606*5184Sek110237 1607*5184Sek110237 /* Get the name of the flowop */ 1608*5184Sek110237 if (attr = get_attr(cmd, FSA_NAME)) { 1609*5184Sek110237 name = *attr->attr_string; 1610*5184Sek110237 } else { 1611*5184Sek110237 filebench_log(LOG_ERROR, 1612*5184Sek110237 "define flowop: flowop %s specifies no name", 1613*5184Sek110237 flowop_type->fo_name); 1614*5184Sek110237 filebench_shutdown(1); 1615*5184Sek110237 } 1616*5184Sek110237 1617*5184Sek110237 if ((flowop = flowop_define(thread, name, 1618*5184Sek110237 flowop_type, FLOW_MASTER, 0)) == NULL) { 1619*5184Sek110237 filebench_log(LOG_ERROR, 1620*5184Sek110237 "define flowop: Failed to instantiate flowop %s\n", 1621*5184Sek110237 cmd->cmd_name); 1622*5184Sek110237 filebench_shutdown(1); 1623*5184Sek110237 } 1624*5184Sek110237 1625*5184Sek110237 /* Get the filename from attribute */ 1626*5184Sek110237 if (attr = get_attr(cmd, FSA_FILE)) { 1627*5184Sek110237 flowop->fo_file = fileobj_find(*attr->attr_string); 1628*5184Sek110237 flowop->fo_fileset = fileset_find(*attr->attr_string); 1629*5184Sek110237 1630*5184Sek110237 if ((flowop->fo_file == NULL) && 1631*5184Sek110237 (flowop->fo_fileset == NULL)) { 1632*5184Sek110237 filebench_log(LOG_ERROR, 1633*5184Sek110237 "define flowop: file %s not found", 1634*5184Sek110237 *attr->attr_string); 1635*5184Sek110237 filebench_shutdown(1); 1636*5184Sek110237 } 1637*5184Sek110237 } 1638*5184Sek110237 1639*5184Sek110237 /* Get the iosize of the op */ 1640*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_IOSIZE)) 1641*5184Sek110237 flowop->fo_iosize = attr->attr_integer; 1642*5184Sek110237 else 1643*5184Sek110237 flowop->fo_iosize = integer_alloc(0); 1644*5184Sek110237 1645*5184Sek110237 /* Get the working set size of the op */ 1646*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_WSS)) 1647*5184Sek110237 flowop->fo_wss = attr->attr_integer; 1648*5184Sek110237 else 1649*5184Sek110237 flowop->fo_wss = integer_alloc(0); 1650*5184Sek110237 1651*5184Sek110237 /* Random I/O? */ 1652*5184Sek110237 if (attr = get_attr_bool(cmd, FSA_RANDOM)) 1653*5184Sek110237 flowop->fo_random = attr->attr_integer; 1654*5184Sek110237 else 1655*5184Sek110237 flowop->fo_random = integer_alloc(0); 1656*5184Sek110237 1657*5184Sek110237 /* Sync I/O? */ 1658*5184Sek110237 if (attr = get_attr_bool(cmd, FSA_DSYNC)) 1659*5184Sek110237 flowop->fo_dsync = attr->attr_integer; 1660*5184Sek110237 else 1661*5184Sek110237 flowop->fo_dsync = integer_alloc(0); 1662*5184Sek110237 1663*5184Sek110237 /* Iterations */ 1664*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_ITERS)) 1665*5184Sek110237 flowop->fo_iters = attr->attr_integer; 1666*5184Sek110237 else 1667*5184Sek110237 flowop->fo_iters = integer_alloc(1); 1668*5184Sek110237 1669*5184Sek110237 1670*5184Sek110237 /* Target, for wakeup etc */ 1671*5184Sek110237 if (attr = get_attr(cmd, FSA_TARGET)) 1672*5184Sek110237 (void) strcpy(flowop->fo_targetname, *attr->attr_string); 1673*5184Sek110237 1674*5184Sek110237 /* Value */ 1675*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_VALUE)) 1676*5184Sek110237 flowop->fo_value = attr->attr_integer; 1677*5184Sek110237 else 1678*5184Sek110237 flowop->fo_value = integer_alloc(0); 1679*5184Sek110237 1680*5184Sek110237 /* FD */ 1681*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_FD)) 1682*5184Sek110237 flowop->fo_fdnumber = *attr->attr_integer; 1683*5184Sek110237 1684*5184Sek110237 /* Rotatefd? */ 1685*5184Sek110237 if (attr = get_attr_bool(cmd, FSA_ROTATEFD)) 1686*5184Sek110237 flowop->fo_rotatefd = attr->attr_integer; 1687*5184Sek110237 else 1688*5184Sek110237 flowop->fo_rotatefd = integer_alloc(0); 1689*5184Sek110237 1690*5184Sek110237 /* SRC FD, for copies etc... */ 1691*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_SRCFD)) 1692*5184Sek110237 flowop->fo_srcfdnumber = *attr->attr_integer; 1693*5184Sek110237 1694*5184Sek110237 /* Blocking operation? */ 1695*5184Sek110237 if (attr = get_attr_bool(cmd, FSA_BLOCKING)) 1696*5184Sek110237 flowop->fo_blocking = attr->attr_integer; 1697*5184Sek110237 else 1698*5184Sek110237 flowop->fo_blocking = integer_alloc(0); 1699*5184Sek110237 1700*5184Sek110237 /* Blocking operation? */ 1701*5184Sek110237 if (attr = get_attr_bool(cmd, FSA_DIRECTIO)) 1702*5184Sek110237 flowop->fo_directio = attr->attr_integer; 1703*5184Sek110237 else 1704*5184Sek110237 flowop->fo_directio = integer_alloc(0); 1705*5184Sek110237 1706*5184Sek110237 /* Highwater mark */ 1707*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_HIGHWATER)) 1708*5184Sek110237 flowop->fo_highwater = attr->attr_integer; 1709*5184Sek110237 else 1710*5184Sek110237 flowop->fo_highwater = integer_alloc(1); 1711*5184Sek110237 } 1712*5184Sek110237 1713*5184Sek110237 /* 1714*5184Sek110237 * Calls fileobj_define() to allocate a fileobj with the supplied name 1715*5184Sek110237 * and initializes the fileobj's pathname attribute, fo_path and fo_create, 1716*5184Sek110237 * and optionally the fo_prealloc, fo_paralloc, fo_reuse, fo_cached, 1717*5184Sek110237 * and fo_size attributes. 1718*5184Sek110237 */ 1719*5184Sek110237 static void 1720*5184Sek110237 parser_file_define(cmd_t *cmd) 1721*5184Sek110237 { 1722*5184Sek110237 fileobj_t *fileobj; 1723*5184Sek110237 char *name; 1724*5184Sek110237 attr_t *attr; 1725*5184Sek110237 var_string_t pathname; 1726*5184Sek110237 1727*5184Sek110237 /* Get the name of the file */ 1728*5184Sek110237 if (attr = get_attr(cmd, FSA_NAME)) { 1729*5184Sek110237 name = *attr->attr_string; 1730*5184Sek110237 } else { 1731*5184Sek110237 filebench_log(LOG_ERROR, 1732*5184Sek110237 "define file: file specifies no name"); 1733*5184Sek110237 return; 1734*5184Sek110237 } 1735*5184Sek110237 1736*5184Sek110237 if ((fileobj = fileobj_define(name)) == NULL) { 1737*5184Sek110237 filebench_log(LOG_ERROR, 1738*5184Sek110237 "define file: failed to instantiate file %s\n", 1739*5184Sek110237 cmd->cmd_name); 1740*5184Sek110237 return; 1741*5184Sek110237 } 1742*5184Sek110237 1743*5184Sek110237 /* Get the pathname from attribute */ 1744*5184Sek110237 if ((attr = get_attr(cmd, FSA_PATH)) == NULL) { 1745*5184Sek110237 filebench_log(LOG_ERROR, 1746*5184Sek110237 "define file: no pathname specified"); 1747*5184Sek110237 return; 1748*5184Sek110237 } 1749*5184Sek110237 1750*5184Sek110237 /* Expand variables in pathname */ 1751*5184Sek110237 if ((pathname = parser_list2varstring(attr->attr_param_list)) 1752*5184Sek110237 == NULL) { 1753*5184Sek110237 filebench_log(LOG_ERROR, "Cannot interpret path"); 1754*5184Sek110237 return; 1755*5184Sek110237 } 1756*5184Sek110237 1757*5184Sek110237 fileobj->fo_path = pathname; 1758*5184Sek110237 1759*5184Sek110237 /* For now, all files are pre-created */ 1760*5184Sek110237 fileobj->fo_create = integer_alloc(1); 1761*5184Sek110237 1762*5184Sek110237 /* Should we preallocate? */ 1763*5184Sek110237 if (attr = get_attr_bool(cmd, FSA_PREALLOC)) { 1764*5184Sek110237 fileobj->fo_prealloc = attr->attr_integer; 1765*5184Sek110237 } else 1766*5184Sek110237 fileobj->fo_prealloc = integer_alloc(0); 1767*5184Sek110237 1768*5184Sek110237 /* Should we prealloc in parallel? */ 1769*5184Sek110237 if (attr = get_attr_bool(cmd, FSA_PARALLOC)) { 1770*5184Sek110237 fileobj->fo_paralloc = attr->attr_integer; 1771*5184Sek110237 } else 1772*5184Sek110237 fileobj->fo_paralloc = integer_alloc(0); 1773*5184Sek110237 1774*5184Sek110237 /* Should we reuse the existing file? */ 1775*5184Sek110237 if (attr = get_attr_bool(cmd, FSA_REUSE)) { 1776*5184Sek110237 fileobj->fo_reuse = attr->attr_integer; 1777*5184Sek110237 } else 1778*5184Sek110237 fileobj->fo_reuse = integer_alloc(0); 1779*5184Sek110237 1780*5184Sek110237 /* Should we leave in cache? */ 1781*5184Sek110237 if (attr = get_attr_bool(cmd, FSA_CACHED)) { 1782*5184Sek110237 fileobj->fo_cached = attr->attr_integer; 1783*5184Sek110237 } else 1784*5184Sek110237 fileobj->fo_cached = integer_alloc(0); 1785*5184Sek110237 1786*5184Sek110237 /* Get the size of the file */ 1787*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_SIZE)) { 1788*5184Sek110237 fileobj->fo_size = attr->attr_integer; 1789*5184Sek110237 } else 1790*5184Sek110237 fileobj->fo_size = integer_alloc(0); 1791*5184Sek110237 1792*5184Sek110237 } 1793*5184Sek110237 1794*5184Sek110237 /* 1795*5184Sek110237 * Calls fileset_define() to allocate a fileset with the supplied name and 1796*5184Sek110237 * initializes the fileset's pathname attribute, and optionally the fs_cached, 1797*5184Sek110237 * fs_reuse, fs_preallocpercent, fs_prealloc, fs_entries, fs_dirwidth, 1798*5184Sek110237 * fs_size, fs_dirgamma, and fs_sizegamma attributes. 1799*5184Sek110237 */ 1800*5184Sek110237 static void 1801*5184Sek110237 parser_fileset_define(cmd_t *cmd) 1802*5184Sek110237 { 1803*5184Sek110237 fileset_t *fileset; 1804*5184Sek110237 char *name; 1805*5184Sek110237 attr_t *attr; 1806*5184Sek110237 var_string_t pathname; 1807*5184Sek110237 1808*5184Sek110237 /* Get the name of the file */ 1809*5184Sek110237 if (attr = get_attr(cmd, FSA_NAME)) { 1810*5184Sek110237 name = *attr->attr_string; 1811*5184Sek110237 } else { 1812*5184Sek110237 filebench_log(LOG_ERROR, 1813*5184Sek110237 "define file: file specifies no name"); 1814*5184Sek110237 return; 1815*5184Sek110237 } 1816*5184Sek110237 1817*5184Sek110237 if ((fileset = fileset_define(name)) == NULL) { 1818*5184Sek110237 filebench_log(LOG_ERROR, 1819*5184Sek110237 "define file: failed to instantiate file %s\n", 1820*5184Sek110237 cmd->cmd_name); 1821*5184Sek110237 return; 1822*5184Sek110237 } 1823*5184Sek110237 1824*5184Sek110237 /* Get the pathname from attribute */ 1825*5184Sek110237 if ((attr = get_attr(cmd, FSA_PATH)) == NULL) { 1826*5184Sek110237 filebench_log(LOG_ERROR, "define file: no pathname specified"); 1827*5184Sek110237 return; 1828*5184Sek110237 } 1829*5184Sek110237 1830*5184Sek110237 /* Expand variables in pathname */ 1831*5184Sek110237 if ((pathname = parser_list2varstring(attr->attr_param_list)) == NULL) { 1832*5184Sek110237 filebench_log(LOG_ERROR, "Cannot interpret path"); 1833*5184Sek110237 return; 1834*5184Sek110237 } 1835*5184Sek110237 1836*5184Sek110237 fileset->fs_path = pathname; 1837*5184Sek110237 1838*5184Sek110237 /* Should we leave in cache? */ 1839*5184Sek110237 if (attr = get_attr_bool(cmd, FSA_CACHED)) { 1840*5184Sek110237 fileset->fs_cached = attr->attr_integer; 1841*5184Sek110237 } else 1842*5184Sek110237 fileset->fs_cached = integer_alloc(0); 1843*5184Sek110237 1844*5184Sek110237 /* Should we reuse the existing file? */ 1845*5184Sek110237 if (attr = get_attr_bool(cmd, FSA_REUSE)) { 1846*5184Sek110237 fileset->fs_reuse = attr->attr_integer; 1847*5184Sek110237 } else 1848*5184Sek110237 fileset->fs_reuse = integer_alloc(0); 1849*5184Sek110237 1850*5184Sek110237 /* How much should we prealloc */ 1851*5184Sek110237 if ((attr = get_attr_integer(cmd, FSA_PREALLOC)) && 1852*5184Sek110237 attr->attr_integer) { 1853*5184Sek110237 fileset->fs_preallocpercent = attr->attr_integer; 1854*5184Sek110237 } else if (attr && !attr->attr_integer) { 1855*5184Sek110237 fileset->fs_preallocpercent = integer_alloc(100); 1856*5184Sek110237 } else { 1857*5184Sek110237 fileset->fs_preallocpercent = integer_alloc(0); 1858*5184Sek110237 } 1859*5184Sek110237 1860*5184Sek110237 /* Should we preallocate? */ 1861*5184Sek110237 if (attr = get_attr_bool(cmd, FSA_PREALLOC)) { 1862*5184Sek110237 fileset->fs_prealloc = attr->attr_integer; 1863*5184Sek110237 } else 1864*5184Sek110237 fileset->fs_prealloc = integer_alloc(0); 1865*5184Sek110237 1866*5184Sek110237 /* Get the size of the fileset */ 1867*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_ENTRIES)) { 1868*5184Sek110237 fileset->fs_entries = attr->attr_integer; 1869*5184Sek110237 } else { 1870*5184Sek110237 filebench_log(LOG_ERROR, "Fileset has zero entries"); 1871*5184Sek110237 fileset->fs_entries = integer_alloc(0); 1872*5184Sek110237 } 1873*5184Sek110237 1874*5184Sek110237 /* Get the mean dir width of the fileset */ 1875*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_DIRWIDTH)) { 1876*5184Sek110237 fileset->fs_dirwidth = attr->attr_integer; 1877*5184Sek110237 } else { 1878*5184Sek110237 filebench_log(LOG_ERROR, "Fileset has zero directory width"); 1879*5184Sek110237 fileset->fs_dirwidth = integer_alloc(0); 1880*5184Sek110237 } 1881*5184Sek110237 1882*5184Sek110237 /* Get the mean or absolute size of the file */ 1883*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_SIZE)) { 1884*5184Sek110237 fileset->fs_size = attr->attr_integer; 1885*5184Sek110237 } else 1886*5184Sek110237 fileset->fs_size = integer_alloc(0); 1887*5184Sek110237 1888*5184Sek110237 /* Get the gamma value for dir width distributions */ 1889*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_DIRGAMMA)) { 1890*5184Sek110237 fileset->fs_dirgamma = attr->attr_integer; 1891*5184Sek110237 } else 1892*5184Sek110237 fileset->fs_dirgamma = integer_alloc(1500); 1893*5184Sek110237 1894*5184Sek110237 /* Get the gamma value for dir width distributions */ 1895*5184Sek110237 if (attr = get_attr_integer(cmd, FSA_FILESIZEGAMMA)) { 1896*5184Sek110237 fileset->fs_sizegamma = attr->attr_integer; 1897*5184Sek110237 } else 1898*5184Sek110237 fileset->fs_sizegamma = integer_alloc(1500); 1899*5184Sek110237 } 1900*5184Sek110237 1901*5184Sek110237 /* 1902*5184Sek110237 * Creates and starts all defined procflow processes. The call to 1903*5184Sek110237 * procflow_init() results in creation of the requested number of 1904*5184Sek110237 * process instances for each previously defined procflow. The 1905*5184Sek110237 * child processes exec() a new instance of filebench, passing it 1906*5184Sek110237 * the instance number and address of the shared memory region. 1907*5184Sek110237 * The child processes will then create their threads and flowops. 1908*5184Sek110237 * The routine then unlocks the run_lock to allow all the processes' 1909*5184Sek110237 * threads to start and waits for all of them to begin execution. 1910*5184Sek110237 * Finally, it records the start time and resets the event generation 1911*5184Sek110237 * system. 1912*5184Sek110237 */ 1913*5184Sek110237 static void 1914*5184Sek110237 parser_proc_create(cmd_t *cmd) 1915*5184Sek110237 { 1916*5184Sek110237 if (procflow_init() != 0) { 1917*5184Sek110237 filebench_log(LOG_ERROR, "Failed to create processes\n"); 1918*5184Sek110237 filebench_shutdown(1); 1919*5184Sek110237 } 1920*5184Sek110237 1921*5184Sek110237 /* Release the read lock, allowing threads to start */ 1922*5184Sek110237 (void) pthread_rwlock_unlock(&filebench_shm->run_lock); 1923*5184Sek110237 1924*5184Sek110237 /* Wait for all threads to start */ 1925*5184Sek110237 if (procflow_allstarted() != 0) { 1926*5184Sek110237 filebench_log(LOG_ERROR, "Could not start run"); 1927*5184Sek110237 return; 1928*5184Sek110237 } 1929*5184Sek110237 1930*5184Sek110237 1931*5184Sek110237 if (filebench_shm->shm_required && 1932*5184Sek110237 (ipc_ismcreate(filebench_shm->shm_required) < 0)) { 1933*5184Sek110237 filebench_log(LOG_ERROR, "Could not allocate shared memory"); 1934*5184Sek110237 return; 1935*5184Sek110237 } 1936*5184Sek110237 1937*5184Sek110237 filebench_shm->starttime = gethrtime(); 1938*5184Sek110237 eventgen_reset(); 1939*5184Sek110237 } 1940*5184Sek110237 1941*5184Sek110237 /* 1942*5184Sek110237 * Calls fileobj_init() to create and optionally pre fill files 1943*5184Sek110237 * for all fileobjs on the master list of fileobjs (filelist). 1944*5184Sek110237 * If errors are encountered, calls filebench_shutdown() 1945*5184Sek110237 * to exit filebench. 1946*5184Sek110237 */ 1947*5184Sek110237 static void 1948*5184Sek110237 parser_file_create(cmd_t *cmd) 1949*5184Sek110237 { 1950*5184Sek110237 fileobj_t *fileobj; 1951*5184Sek110237 1952*5184Sek110237 if (fileobj_init() != 0) { 1953*5184Sek110237 filebench_log(LOG_ERROR, "Failed to create files"); 1954*5184Sek110237 filebench_shutdown(1); 1955*5184Sek110237 } 1956*5184Sek110237 } 1957*5184Sek110237 1958*5184Sek110237 /* 1959*5184Sek110237 * Calls fileset_createset() to populate all filesets and create all 1960*5184Sek110237 * associated, initially existant, files and subdirectories. 1961*5184Sek110237 * If errors are encountered, calls filebench_shutdown() 1962*5184Sek110237 * to exit filebench. 1963*5184Sek110237 */ 1964*5184Sek110237 static void 1965*5184Sek110237 parser_fileset_create(cmd_t *cmd) 1966*5184Sek110237 { 1967*5184Sek110237 fileset_t *fileset; 1968*5184Sek110237 1969*5184Sek110237 if (fileset_createset(NULL) != 0) { 1970*5184Sek110237 filebench_log(LOG_ERROR, "Failed to create filesets"); 1971*5184Sek110237 filebench_shutdown(1); 1972*5184Sek110237 } 1973*5184Sek110237 } 1974*5184Sek110237 1975*5184Sek110237 /* 1976*5184Sek110237 * Shuts down all processes and their associated threads. When finished 1977*5184Sek110237 * it deletes interprocess shared memory and resets the event generator. 1978*5184Sek110237 * It does not exit the filebench program though. 1979*5184Sek110237 */ 1980*5184Sek110237 static void 1981*5184Sek110237 parser_proc_shutdown(cmd_t *cmd) 1982*5184Sek110237 { 1983*5184Sek110237 filebench_log(LOG_INFO, "Shutting down processes"); 1984*5184Sek110237 procflow_shutdown(); 1985*5184Sek110237 if (filebench_shm->shm_required) 1986*5184Sek110237 ipc_ismdelete(); 1987*5184Sek110237 eventgen_reset(); 1988*5184Sek110237 } 1989*5184Sek110237 1990*5184Sek110237 /* 1991*5184Sek110237 * Ends filebench run after first destoring any interprocess 1992*5184Sek110237 * shared memory. The call to filebench_shutdown() 1993*5184Sek110237 * also causes filebench to exit. 1994*5184Sek110237 */ 1995*5184Sek110237 static void 1996*5184Sek110237 parser_filebench_shutdown(cmd_t *cmd) 1997*5184Sek110237 { 1998*5184Sek110237 ipc_cleanup(); 1999*5184Sek110237 filebench_shutdown(1); 2000*5184Sek110237 } 2001*5184Sek110237 2002*5184Sek110237 /* 2003*5184Sek110237 * Sleeps for cmd->cmd_qty seconds, one second at a time. 2004*5184Sek110237 */ 2005*5184Sek110237 static void 2006*5184Sek110237 parser_sleep(cmd_t *cmd) 2007*5184Sek110237 { 2008*5184Sek110237 int sleeptime; 2009*5184Sek110237 2010*5184Sek110237 /* check for startup errors */ 2011*5184Sek110237 if (filebench_shm->f_abort) 2012*5184Sek110237 return; 2013*5184Sek110237 2014*5184Sek110237 sleeptime = cmd->cmd_qty; 2015*5184Sek110237 filebench_log(LOG_INFO, "Running..."); 2016*5184Sek110237 while (sleeptime) { 2017*5184Sek110237 (void) sleep(1); 2018*5184Sek110237 sleeptime--; 2019*5184Sek110237 if (filebench_shm->f_abort) 2020*5184Sek110237 break; 2021*5184Sek110237 } 2022*5184Sek110237 filebench_log(LOG_INFO, "Run took %lld seconds...", 2023*5184Sek110237 cmd->cmd_qty - sleeptime); 2024*5184Sek110237 } 2025*5184Sek110237 2026*5184Sek110237 /* 2027*5184Sek110237 * Do a file bench run. Calls routines to create file sets, files, and 2028*5184Sek110237 * processes. It resets the statistics counters, then sleeps for the runtime 2029*5184Sek110237 * passed as an argument to it on the command line in 1 second increments. 2030*5184Sek110237 * When it is finished sleeping, it collects a snapshot of the statistics 2031*5184Sek110237 * and ends the run. 2032*5184Sek110237 */ 2033*5184Sek110237 static void 2034*5184Sek110237 parser_run(cmd_t *cmd) 2035*5184Sek110237 { 2036*5184Sek110237 int runtime; 2037*5184Sek110237 2038*5184Sek110237 runtime = cmd->cmd_qty; 2039*5184Sek110237 parser_fileset_create(cmd); 2040*5184Sek110237 parser_file_create(cmd); 2041*5184Sek110237 parser_proc_create(cmd); 2042*5184Sek110237 2043*5184Sek110237 /* check for startup errors */ 2044*5184Sek110237 if (filebench_shm->f_abort) 2045*5184Sek110237 return; 2046*5184Sek110237 2047*5184Sek110237 filebench_log(LOG_INFO, "Running..."); 2048*5184Sek110237 stats_clear(); 2049*5184Sek110237 while (runtime) { 2050*5184Sek110237 (void) sleep(1); 2051*5184Sek110237 runtime--; 2052*5184Sek110237 if (filebench_shm->f_abort) 2053*5184Sek110237 break; 2054*5184Sek110237 } 2055*5184Sek110237 filebench_log(LOG_INFO, "Run took %lld seconds...", 2056*5184Sek110237 cmd->cmd_qty - runtime); 2057*5184Sek110237 parser_statssnap(cmd); 2058*5184Sek110237 parser_proc_shutdown(cmd); 2059*5184Sek110237 } 2060*5184Sek110237 2061*5184Sek110237 /* 2062*5184Sek110237 * Similar to parser_run, but gets the sleep time from a variable 2063*5184Sek110237 * whose name is supplied as an argument to the command. 2064*5184Sek110237 */ 2065*5184Sek110237 static void 2066*5184Sek110237 parser_run_variable(cmd_t *cmd) 2067*5184Sek110237 { 2068*5184Sek110237 vinteger_t *integer = var_ref_integer(cmd->cmd_tgt1); 2069*5184Sek110237 int runtime; 2070*5184Sek110237 2071*5184Sek110237 if (integer == NULL) { 2072*5184Sek110237 filebench_log(LOG_ERROR, "Unknown variable %s", 2073*5184Sek110237 cmd->cmd_tgt1); 2074*5184Sek110237 return; 2075*5184Sek110237 } 2076*5184Sek110237 2077*5184Sek110237 runtime = *integer; 2078*5184Sek110237 2079*5184Sek110237 /* check for startup errors */ 2080*5184Sek110237 if (filebench_shm->f_abort) 2081*5184Sek110237 return; 2082*5184Sek110237 2083*5184Sek110237 filebench_log(LOG_INFO, "Running..."); 2084*5184Sek110237 stats_clear(); 2085*5184Sek110237 while (runtime) { 2086*5184Sek110237 (void) sleep(1); 2087*5184Sek110237 runtime--; 2088*5184Sek110237 if (filebench_shm->f_abort) 2089*5184Sek110237 break; 2090*5184Sek110237 } 2091*5184Sek110237 filebench_log(LOG_INFO, "Run took %lld seconds...", 2092*5184Sek110237 *integer - runtime); 2093*5184Sek110237 parser_statssnap(cmd); 2094*5184Sek110237 } 2095*5184Sek110237 2096*5184Sek110237 char *usagestr = NULL; 2097*5184Sek110237 2098*5184Sek110237 /* 2099*5184Sek110237 * Prints usage string if defined, else just a message requesting load of a 2100*5184Sek110237 * personality. 2101*5184Sek110237 */ 2102*5184Sek110237 static void 2103*5184Sek110237 parser_help(cmd_t *cmd) 2104*5184Sek110237 { 2105*5184Sek110237 int runtime; 2106*5184Sek110237 2107*5184Sek110237 if (usagestr) { 2108*5184Sek110237 filebench_log(LOG_INFO, "%s", usagestr); 2109*5184Sek110237 } else { 2110*5184Sek110237 filebench_log(LOG_INFO, 2111*5184Sek110237 "load <personality> (ls " 2112*5184Sek110237 "/usr/benchmarks/filebench/workloads for list)"); 2113*5184Sek110237 } 2114*5184Sek110237 } 2115*5184Sek110237 2116*5184Sek110237 char *varstr = NULL; 2117*5184Sek110237 2118*5184Sek110237 /* 2119*5184Sek110237 * Prints the string of all var definitions, if there is one. 2120*5184Sek110237 */ 2121*5184Sek110237 static void 2122*5184Sek110237 parser_printvars(cmd_t *cmd) 2123*5184Sek110237 { 2124*5184Sek110237 int runtime; 2125*5184Sek110237 char *str, *c; 2126*5184Sek110237 2127*5184Sek110237 if (varstr) { 2128*5184Sek110237 str = strdup(varstr); 2129*5184Sek110237 for (c = str; *c != '\0'; c++) { 2130*5184Sek110237 if ((char)*c == '$') 2131*5184Sek110237 *c = ' '; 2132*5184Sek110237 } 2133*5184Sek110237 filebench_log(LOG_INFO, "%s", str); 2134*5184Sek110237 free(str); 2135*5184Sek110237 } 2136*5184Sek110237 } 2137*5184Sek110237 2138*5184Sek110237 /* 2139*5184Sek110237 * Used by the SET command to add a var and default value string to the 2140*5184Sek110237 * varstr string. It allocates a new, larger varstr string, copies the 2141*5184Sek110237 * old contents of varstr into it, then adds the new var string on the end. 2142*5184Sek110237 */ 2143*5184Sek110237 static void 2144*5184Sek110237 parser_vars(cmd_t *cmd) 2145*5184Sek110237 { 2146*5184Sek110237 char *string = cmd->cmd_tgt1; 2147*5184Sek110237 char *newvars; 2148*5184Sek110237 2149*5184Sek110237 if (string == NULL) 2150*5184Sek110237 return; 2151*5184Sek110237 2152*5184Sek110237 if (dofile) 2153*5184Sek110237 return; 2154*5184Sek110237 2155*5184Sek110237 if (varstr == NULL) { 2156*5184Sek110237 newvars = malloc(strlen(string) + 2); 2157*5184Sek110237 *newvars = 0; 2158*5184Sek110237 } else { 2159*5184Sek110237 newvars = malloc(strlen(varstr) + strlen(string) + 2); 2160*5184Sek110237 (void) strcpy(newvars, varstr); 2161*5184Sek110237 } 2162*5184Sek110237 (void) strcat(newvars, string); 2163*5184Sek110237 (void) strcat(newvars, " "); 2164*5184Sek110237 2165*5184Sek110237 if (varstr) 2166*5184Sek110237 free(varstr); 2167*5184Sek110237 2168*5184Sek110237 varstr = newvars; 2169*5184Sek110237 } 2170*5184Sek110237 2171*5184Sek110237 /* 2172*5184Sek110237 * Same as parser_sleep, except the sleep time is obtained from a variable 2173*5184Sek110237 * whose name is passed to it as an argument on the command line. 2174*5184Sek110237 */ 2175*5184Sek110237 static void 2176*5184Sek110237 parser_sleep_variable(cmd_t *cmd) 2177*5184Sek110237 { 2178*5184Sek110237 vinteger_t *integer = var_ref_integer(cmd->cmd_tgt1); 2179*5184Sek110237 int sleeptime; 2180*5184Sek110237 2181*5184Sek110237 if (integer == NULL) { 2182*5184Sek110237 filebench_log(LOG_ERROR, "Unknown variable %s", 2183*5184Sek110237 cmd->cmd_tgt1); 2184*5184Sek110237 return; 2185*5184Sek110237 } 2186*5184Sek110237 2187*5184Sek110237 sleeptime = *integer; 2188*5184Sek110237 2189*5184Sek110237 /* check for startup errors */ 2190*5184Sek110237 if (filebench_shm->f_abort) 2191*5184Sek110237 return; 2192*5184Sek110237 2193*5184Sek110237 filebench_log(LOG_INFO, "Running..."); 2194*5184Sek110237 while (sleeptime) { 2195*5184Sek110237 (void) sleep(1); 2196*5184Sek110237 sleeptime--; 2197*5184Sek110237 if (filebench_shm->f_abort) 2198*5184Sek110237 break; 2199*5184Sek110237 } 2200*5184Sek110237 filebench_log(LOG_INFO, "Run took %lld seconds...", 2201*5184Sek110237 *integer - sleeptime); 2202*5184Sek110237 } 2203*5184Sek110237 2204*5184Sek110237 /* 2205*5184Sek110237 * Parser log prints the values of a list of variables to the log file. 2206*5184Sek110237 * The list of variables is placed on the command line, separated 2207*5184Sek110237 * by comas and the entire list is enclosed in quotes. 2208*5184Sek110237 * For example, if $dir contains "/export/home/tmp" and $filesize = 1048576, 2209*5184Sek110237 * then typing: log "$dir, $filesize" prints: log /export/home/tmp, 1048576 2210*5184Sek110237 */ 2211*5184Sek110237 static void 2212*5184Sek110237 parser_log(cmd_t *cmd) 2213*5184Sek110237 { 2214*5184Sek110237 char *string; 2215*5184Sek110237 2216*5184Sek110237 if (cmd->cmd_param_list == NULL) 2217*5184Sek110237 return; 2218*5184Sek110237 2219*5184Sek110237 string = parser_list2string(cmd->cmd_param_list); 2220*5184Sek110237 2221*5184Sek110237 if (string == NULL) 2222*5184Sek110237 return; 2223*5184Sek110237 2224*5184Sek110237 filebench_log(LOG_VERBOSE, "log %s", string); 2225*5184Sek110237 filebench_log(LOG_LOG, "%s", string); 2226*5184Sek110237 } 2227*5184Sek110237 2228*5184Sek110237 /* 2229*5184Sek110237 * Implements the stats directory command. changes the directory for 2230*5184Sek110237 * dumping statistics to supplied directory path. For example: 2231*5184Sek110237 * stats directory /tmp 2232*5184Sek110237 * changes the stats directory to "/tmp". 2233*5184Sek110237 */ 2234*5184Sek110237 static void 2235*5184Sek110237 parser_directory(cmd_t *cmd) 2236*5184Sek110237 { 2237*5184Sek110237 char newdir[MAXPATHLEN]; 2238*5184Sek110237 char *dir; 2239*5184Sek110237 2240*5184Sek110237 if ((dir = parser_list2string(cmd->cmd_param_list)) == NULL) { 2241*5184Sek110237 filebench_log(LOG_ERROR, "Cannot interpret directory"); 2242*5184Sek110237 return; 2243*5184Sek110237 } 2244*5184Sek110237 2245*5184Sek110237 *newdir = 0; 2246*5184Sek110237 /* Change dir relative to cwd if path not fully qualified */ 2247*5184Sek110237 if (*dir != '/') { 2248*5184Sek110237 (void) strcat(newdir, cwd); 2249*5184Sek110237 (void) strcat(newdir, "/"); 2250*5184Sek110237 } 2251*5184Sek110237 (void) strcat(newdir, dir); 2252*5184Sek110237 (void) mkdir(newdir, 0755); 2253*5184Sek110237 filebench_log(LOG_VERBOSE, "Change dir to %s", newdir); 2254*5184Sek110237 chdir(newdir); 2255*5184Sek110237 free(dir); 2256*5184Sek110237 } 2257*5184Sek110237 2258*5184Sek110237 #define PIPE_PARENT 1 2259*5184Sek110237 #define PIPE_CHILD 0 2260*5184Sek110237 2261*5184Sek110237 /* 2262*5184Sek110237 * Runs the quoted unix command as a background process. Intended for 2263*5184Sek110237 * running statistics gathering utilities such as mpstat while the filebench 2264*5184Sek110237 * workload is running. Also records the pid's of the background processes 2265*5184Sek110237 * so that parser_statssnap() can terminate them when the run completes. 2266*5184Sek110237 */ 2267*5184Sek110237 static void 2268*5184Sek110237 parser_statscmd(cmd_t *cmd) 2269*5184Sek110237 { 2270*5184Sek110237 char *string; 2271*5184Sek110237 pid_t pid; 2272*5184Sek110237 pidlist_t *pidlistent; 2273*5184Sek110237 int pipe_fd[2]; 2274*5184Sek110237 int newstdout; 2275*5184Sek110237 2276*5184Sek110237 if (cmd->cmd_param_list == NULL) 2277*5184Sek110237 return; 2278*5184Sek110237 2279*5184Sek110237 string = parser_list2string(cmd->cmd_param_list); 2280*5184Sek110237 2281*5184Sek110237 if (string == NULL) 2282*5184Sek110237 return; 2283*5184Sek110237 2284*5184Sek110237 if ((pipe(pipe_fd)) < 0) { 2285*5184Sek110237 filebench_log(LOG_ERROR, "statscmd pipe failed"); 2286*5184Sek110237 return; 2287*5184Sek110237 } 2288*5184Sek110237 2289*5184Sek110237 #ifdef HAVE_FORK1 2290*5184Sek110237 if ((pid = fork1()) < 0) { 2291*5184Sek110237 filebench_log(LOG_ERROR, "statscmd fork failed"); 2292*5184Sek110237 return; 2293*5184Sek110237 } 2294*5184Sek110237 #elif HAVE_FORK 2295*5184Sek110237 if ((pid = fork()) < 0) { 2296*5184Sek110237 filebench_log(LOG_ERROR, "statscmd fork failed"); 2297*5184Sek110237 return; 2298*5184Sek110237 } 2299*5184Sek110237 #else 2300*5184Sek110237 Crash! - Need code to deal with no fork1! 2301*5184Sek110237 #endif /* HAVE_FORK1 */ 2302*5184Sek110237 2303*5184Sek110237 if (pid == 0) { 2304*5184Sek110237 2305*5184Sek110237 setsid(); 2306*5184Sek110237 2307*5184Sek110237 filebench_log(LOG_VERBOSE, 2308*5184Sek110237 "Backgrounding %s", string); 2309*5184Sek110237 /* 2310*5184Sek110237 * Child 2311*5184Sek110237 * - close stdout 2312*5184Sek110237 * - dup to create new stdout 2313*5184Sek110237 * - close pipe fds 2314*5184Sek110237 */ 2315*5184Sek110237 (void) close(1); 2316*5184Sek110237 2317*5184Sek110237 if ((newstdout = dup(pipe_fd[PIPE_CHILD])) < 0) { 2318*5184Sek110237 filebench_log(LOG_ERROR, 2319*5184Sek110237 "statscmd dup failed: %s", 2320*5184Sek110237 strerror(errno)); 2321*5184Sek110237 } 2322*5184Sek110237 2323*5184Sek110237 (void) close(pipe_fd[PIPE_PARENT]); 2324*5184Sek110237 (void) close(pipe_fd[PIPE_CHILD]); 2325*5184Sek110237 2326*5184Sek110237 if (system(string) < 0) { 2327*5184Sek110237 filebench_log(LOG_ERROR, 2328*5184Sek110237 "statscmd exec failed: %s", 2329*5184Sek110237 strerror(errno)); 2330*5184Sek110237 } 2331*5184Sek110237 /* Failed! */ 2332*5184Sek110237 exit(1); 2333*5184Sek110237 2334*5184Sek110237 } else { 2335*5184Sek110237 2336*5184Sek110237 /* Record pid in pidlist for subsequent reaping by stats snap */ 2337*5184Sek110237 if ((pidlistent = (pidlist_t *)malloc(sizeof (pidlist_t))) 2338*5184Sek110237 == NULL) { 2339*5184Sek110237 filebench_log(LOG_ERROR, "pidlistent malloc failed"); 2340*5184Sek110237 return; 2341*5184Sek110237 } 2342*5184Sek110237 2343*5184Sek110237 pidlistent->pl_pid = pid; 2344*5184Sek110237 pidlistent->pl_fd = pipe_fd[PIPE_PARENT]; 2345*5184Sek110237 (void) close(pipe_fd[PIPE_CHILD]); 2346*5184Sek110237 2347*5184Sek110237 /* Add fileobj to global list */ 2348*5184Sek110237 if (pidlist == NULL) { 2349*5184Sek110237 pidlist = pidlistent; 2350*5184Sek110237 pidlistent->pl_next = NULL; 2351*5184Sek110237 } else { 2352*5184Sek110237 pidlistent->pl_next = pidlist; 2353*5184Sek110237 pidlist = pidlistent; 2354*5184Sek110237 } 2355*5184Sek110237 } 2356*5184Sek110237 } 2357*5184Sek110237 2358*5184Sek110237 /* 2359*5184Sek110237 * Launches a shell to run the unix command supplied in the argument. 2360*5184Sek110237 * The command should be enclosed in quotes, as in: 2361*5184Sek110237 * system "rm xyz" 2362*5184Sek110237 * which would run the "rm" utility to delete the file "xyz". 2363*5184Sek110237 */ 2364*5184Sek110237 static void 2365*5184Sek110237 parser_system(cmd_t *cmd) 2366*5184Sek110237 { 2367*5184Sek110237 char *string; 2368*5184Sek110237 2369*5184Sek110237 if (cmd->cmd_param_list == NULL) 2370*5184Sek110237 return; 2371*5184Sek110237 2372*5184Sek110237 string = parser_list2string(cmd->cmd_param_list); 2373*5184Sek110237 2374*5184Sek110237 if (string == NULL) 2375*5184Sek110237 return; 2376*5184Sek110237 2377*5184Sek110237 filebench_log(LOG_VERBOSE, 2378*5184Sek110237 "Running '%s'", string); 2379*5184Sek110237 2380*5184Sek110237 if (system(string) < 0) { 2381*5184Sek110237 filebench_log(LOG_ERROR, 2382*5184Sek110237 "system exec failed: %s", 2383*5184Sek110237 strerror(errno)); 2384*5184Sek110237 } 2385*5184Sek110237 free(string); 2386*5184Sek110237 } 2387*5184Sek110237 2388*5184Sek110237 /* 2389*5184Sek110237 * Echos string supplied with command to the log. 2390*5184Sek110237 */ 2391*5184Sek110237 static void 2392*5184Sek110237 parser_echo(cmd_t *cmd) 2393*5184Sek110237 { 2394*5184Sek110237 char *string; 2395*5184Sek110237 2396*5184Sek110237 if (cmd->cmd_param_list == NULL) 2397*5184Sek110237 return; 2398*5184Sek110237 2399*5184Sek110237 string = parser_list2string(cmd->cmd_param_list); 2400*5184Sek110237 2401*5184Sek110237 if (string == NULL) 2402*5184Sek110237 return; 2403*5184Sek110237 2404*5184Sek110237 filebench_log(LOG_INFO, "%s", string); 2405*5184Sek110237 } 2406*5184Sek110237 2407*5184Sek110237 2408*5184Sek110237 /* 2409*5184Sek110237 * Adds the string supplied as the argument to the usage command 2410*5184Sek110237 * to the end of the string printed by the help command. 2411*5184Sek110237 */ 2412*5184Sek110237 static void 2413*5184Sek110237 parser_usage(cmd_t *cmd) 2414*5184Sek110237 { 2415*5184Sek110237 char *string; 2416*5184Sek110237 char *newusage; 2417*5184Sek110237 2418*5184Sek110237 if (cmd->cmd_param_list == NULL) 2419*5184Sek110237 return; 2420*5184Sek110237 2421*5184Sek110237 string = parser_list2string(cmd->cmd_param_list); 2422*5184Sek110237 2423*5184Sek110237 if (string == NULL) 2424*5184Sek110237 return; 2425*5184Sek110237 2426*5184Sek110237 if (dofile) 2427*5184Sek110237 return; 2428*5184Sek110237 2429*5184Sek110237 if (usagestr == NULL) { 2430*5184Sek110237 newusage = malloc(strlen(string) + 2); 2431*5184Sek110237 *newusage = 0; 2432*5184Sek110237 } else { 2433*5184Sek110237 newusage = malloc(strlen(usagestr) + strlen(string) + 2); 2434*5184Sek110237 (void) strcpy(newusage, usagestr); 2435*5184Sek110237 } 2436*5184Sek110237 (void) strcat(newusage, "\n"); 2437*5184Sek110237 (void) strcat(newusage, string); 2438*5184Sek110237 2439*5184Sek110237 if (usagestr) 2440*5184Sek110237 free(usagestr); 2441*5184Sek110237 2442*5184Sek110237 usagestr = newusage; 2443*5184Sek110237 2444*5184Sek110237 filebench_log(LOG_INFO, "%s", string); 2445*5184Sek110237 } 2446*5184Sek110237 2447*5184Sek110237 /* 2448*5184Sek110237 * Updates the global dump filename with the filename supplied 2449*5184Sek110237 * as the command's argument. Then dumps the statistics of each 2450*5184Sek110237 * worker flowop into the dump file, followed by a summary of 2451*5184Sek110237 * overall totals. 2452*5184Sek110237 */ 2453*5184Sek110237 static void 2454*5184Sek110237 parser_statsdump(cmd_t *cmd) 2455*5184Sek110237 { 2456*5184Sek110237 char *string; 2457*5184Sek110237 2458*5184Sek110237 if (cmd->cmd_param_list == NULL) 2459*5184Sek110237 return; 2460*5184Sek110237 2461*5184Sek110237 string = parser_list2string(cmd->cmd_param_list); 2462*5184Sek110237 2463*5184Sek110237 if (string == NULL) 2464*5184Sek110237 return; 2465*5184Sek110237 2466*5184Sek110237 filebench_log(LOG_VERBOSE, 2467*5184Sek110237 "Stats dump to file '%s'", string); 2468*5184Sek110237 2469*5184Sek110237 stats_dump(string); 2470*5184Sek110237 2471*5184Sek110237 free(string); 2472*5184Sek110237 } 2473*5184Sek110237 2474*5184Sek110237 /* 2475*5184Sek110237 * Same as parser_statsdump, but in xml format. 2476*5184Sek110237 */ 2477*5184Sek110237 static void 2478*5184Sek110237 parser_statsxmldump(cmd_t *cmd) 2479*5184Sek110237 { 2480*5184Sek110237 char *string; 2481*5184Sek110237 2482*5184Sek110237 if (cmd->cmd_param_list == NULL) 2483*5184Sek110237 return; 2484*5184Sek110237 2485*5184Sek110237 string = parser_list2string(cmd->cmd_param_list); 2486*5184Sek110237 2487*5184Sek110237 if (string == NULL) 2488*5184Sek110237 return; 2489*5184Sek110237 2490*5184Sek110237 filebench_log(LOG_VERBOSE, 2491*5184Sek110237 "Stats dump to file '%s'", string); 2492*5184Sek110237 2493*5184Sek110237 stats_xmldump(string); 2494*5184Sek110237 2495*5184Sek110237 free(string); 2496*5184Sek110237 } 2497*5184Sek110237 2498*5184Sek110237 /* 2499*5184Sek110237 * Kills off background statistics collection processes, then takes a snapshot 2500*5184Sek110237 * of the filebench run's collected statistics using stats_snap() from 2501*5184Sek110237 * stats.c. 2502*5184Sek110237 */ 2503*5184Sek110237 static void 2504*5184Sek110237 parser_statssnap(cmd_t *cmd) 2505*5184Sek110237 { 2506*5184Sek110237 pidlist_t *pidlistent; 2507*5184Sek110237 int stat; 2508*5184Sek110237 pid_t pid; 2509*5184Sek110237 2510*5184Sek110237 for (pidlistent = pidlist; pidlistent != NULL; 2511*5184Sek110237 pidlistent = pidlistent->pl_next) { 2512*5184Sek110237 filebench_log(LOG_VERBOSE, "Killing session %d for pid %d", 2513*5184Sek110237 getsid(pidlistent->pl_pid), 2514*5184Sek110237 pidlistent->pl_pid); 2515*5184Sek110237 if (pidlistent->pl_fd) 2516*5184Sek110237 (void) close(pidlistent->pl_fd); 2517*5184Sek110237 #ifdef HAVE_SIGSEND 2518*5184Sek110237 sigsend(P_SID, getsid(pidlistent->pl_pid), SIGTERM); 2519*5184Sek110237 #else 2520*5184Sek110237 (void) kill(-1, SIGTERM); 2521*5184Sek110237 #endif 2522*5184Sek110237 2523*5184Sek110237 /* Close pipe */ 2524*5184Sek110237 if (pidlistent->pl_fd) 2525*5184Sek110237 (void) close(pidlistent->pl_fd); 2526*5184Sek110237 2527*5184Sek110237 /* Wait for cmd and all its children */ 2528*5184Sek110237 while ((pid = waitpid(pidlistent->pl_pid * -1, &stat, 0)) > 0) 2529*5184Sek110237 filebench_log(LOG_DEBUG_IMPL, 2530*5184Sek110237 "Waited for pid %lld", pid); 2531*5184Sek110237 } 2532*5184Sek110237 2533*5184Sek110237 for (pidlistent = pidlist; pidlistent != NULL; 2534*5184Sek110237 pidlistent = pidlistent->pl_next) { 2535*5184Sek110237 free(pidlistent); 2536*5184Sek110237 } 2537*5184Sek110237 2538*5184Sek110237 pidlist = NULL; 2539*5184Sek110237 stats_snap(); 2540*5184Sek110237 } 2541*5184Sek110237 2542*5184Sek110237 /* 2543*5184Sek110237 * Shutdown filebench. 2544*5184Sek110237 */ 2545*5184Sek110237 static void 2546*5184Sek110237 parser_abort(int arg) 2547*5184Sek110237 { 2548*5184Sek110237 (void) sigignore(SIGINT); 2549*5184Sek110237 filebench_log(LOG_INFO, "Aborting..."); 2550*5184Sek110237 filebench_shutdown(1); 2551*5184Sek110237 } 2552*5184Sek110237 2553*5184Sek110237 /* 2554*5184Sek110237 * alloc_cmd() allocates the required resources for a cmd_t. On failure, a 2555*5184Sek110237 * filebench_log is issued and NULL is returned. 2556*5184Sek110237 */ 2557*5184Sek110237 static cmd_t * 2558*5184Sek110237 alloc_cmd(void) 2559*5184Sek110237 { 2560*5184Sek110237 cmd_t *cmd; 2561*5184Sek110237 2562*5184Sek110237 if ((cmd = malloc(sizeof (cmd_t))) == NULL) { 2563*5184Sek110237 filebench_log(LOG_ERROR, "Alloc cmd failed"); 2564*5184Sek110237 return (NULL); 2565*5184Sek110237 } 2566*5184Sek110237 2567*5184Sek110237 (void) memset(cmd, 0, sizeof (cmd_t)); 2568*5184Sek110237 2569*5184Sek110237 return (cmd); 2570*5184Sek110237 } 2571*5184Sek110237 2572*5184Sek110237 /* 2573*5184Sek110237 * Frees the resources of a cmd_t and then the cmd_t "cmd" itself. 2574*5184Sek110237 */ 2575*5184Sek110237 static void 2576*5184Sek110237 free_cmd(cmd_t *cmd) 2577*5184Sek110237 { 2578*5184Sek110237 free((void *)cmd->cmd_tgt1); 2579*5184Sek110237 free((void *)cmd->cmd_tgt2); 2580*5184Sek110237 free(cmd); 2581*5184Sek110237 } 2582*5184Sek110237 2583*5184Sek110237 /* 2584*5184Sek110237 * Allocates an attr_t structure and zeros it. Returns NULL on failure, or 2585*5184Sek110237 * a pointer to the attr_t. 2586*5184Sek110237 */ 2587*5184Sek110237 static attr_t * 2588*5184Sek110237 alloc_attr() 2589*5184Sek110237 { 2590*5184Sek110237 attr_t *attr; 2591*5184Sek110237 2592*5184Sek110237 if ((attr = malloc(sizeof (attr_t))) == NULL) { 2593*5184Sek110237 return (NULL); 2594*5184Sek110237 } 2595*5184Sek110237 2596*5184Sek110237 (void) memset(attr, 0, sizeof (attr_t)); 2597*5184Sek110237 return (attr); 2598*5184Sek110237 } 2599*5184Sek110237 2600*5184Sek110237 /* 2601*5184Sek110237 * Searches the attribute list for the command for the named attribute type. 2602*5184Sek110237 * The attribute list is created by the parser from the list of attributes 2603*5184Sek110237 * supplied with certain commands, such as the define and flowop commands. 2604*5184Sek110237 * Returns a pointer to the attribute structure if the named attribute is 2605*5184Sek110237 * found, otherwise returns NULL. If the attribute includes a parameter list, 2606*5184Sek110237 * the list is converted to a string and stored in the attr_string field of 2607*5184Sek110237 * the returned attr_t struct. 2608*5184Sek110237 */ 2609*5184Sek110237 static attr_t * 2610*5184Sek110237 get_attr(cmd_t *cmd, int64_t name) 2611*5184Sek110237 { 2612*5184Sek110237 attr_t *attr; 2613*5184Sek110237 attr_t *rtn = NULL; 2614*5184Sek110237 char *string; 2615*5184Sek110237 2616*5184Sek110237 for (attr = cmd->cmd_attr_list; attr != NULL; 2617*5184Sek110237 attr = attr->attr_next) { 2618*5184Sek110237 filebench_log(LOG_DEBUG_IMPL, 2619*5184Sek110237 "attr %d = %d %llx?", 2620*5184Sek110237 attr->attr_name, 2621*5184Sek110237 name, 2622*5184Sek110237 attr->attr_integer); 2623*5184Sek110237 2624*5184Sek110237 if (attr->attr_name == name) 2625*5184Sek110237 rtn = attr; 2626*5184Sek110237 } 2627*5184Sek110237 2628*5184Sek110237 if (rtn == NULL) 2629*5184Sek110237 return (NULL); 2630*5184Sek110237 2631*5184Sek110237 if (rtn->attr_param_list) { 2632*5184Sek110237 filebench_log(LOG_DEBUG_SCRIPT, "attr is param list"); 2633*5184Sek110237 string = parser_list2string(rtn->attr_param_list); 2634*5184Sek110237 if (string != NULL) { 2635*5184Sek110237 rtn->attr_string = string_alloc(string); 2636*5184Sek110237 filebench_log(LOG_DEBUG_SCRIPT, 2637*5184Sek110237 "attr string %s", string); 2638*5184Sek110237 } 2639*5184Sek110237 } 2640*5184Sek110237 2641*5184Sek110237 return (rtn); 2642*5184Sek110237 } 2643*5184Sek110237 2644*5184Sek110237 /* 2645*5184Sek110237 * Similar to get_attr, but converts the parameter string supplied with the 2646*5184Sek110237 * named attribute to an integer and stores the integer in the attr_integer 2647*5184Sek110237 * portion of the returned attr_t struct. 2648*5184Sek110237 */ 2649*5184Sek110237 static attr_t * 2650*5184Sek110237 get_attr_integer(cmd_t *cmd, int64_t name) 2651*5184Sek110237 { 2652*5184Sek110237 attr_t *attr; 2653*5184Sek110237 attr_t *rtn = NULL; 2654*5184Sek110237 2655*5184Sek110237 for (attr = cmd->cmd_attr_list; attr != NULL; 2656*5184Sek110237 attr = attr->attr_next) { 2657*5184Sek110237 if (attr->attr_name == name) 2658*5184Sek110237 rtn = attr; 2659*5184Sek110237 } 2660*5184Sek110237 2661*5184Sek110237 if (rtn == NULL) 2662*5184Sek110237 return (NULL); 2663*5184Sek110237 2664*5184Sek110237 if (rtn->attr_param_list) { 2665*5184Sek110237 rtn->attr_integer = parser_list2integer(rtn->attr_param_list); 2666*5184Sek110237 } 2667*5184Sek110237 2668*5184Sek110237 return (rtn); 2669*5184Sek110237 } 2670*5184Sek110237 2671*5184Sek110237 /* 2672*5184Sek110237 * Similar to get_attr, but converts the parameter string supplied with the 2673*5184Sek110237 * named attribute to an integer and stores the integer in the attr_integer 2674*5184Sek110237 * portion of the returned attr_t struct. If no parameter string is supplied 2675*5184Sek110237 * then it defaults to TRUE (1). 2676*5184Sek110237 */ 2677*5184Sek110237 static attr_t * 2678*5184Sek110237 get_attr_bool(cmd_t *cmd, int64_t name) 2679*5184Sek110237 { 2680*5184Sek110237 attr_t *attr; 2681*5184Sek110237 attr_t *rtn = NULL; 2682*5184Sek110237 2683*5184Sek110237 for (attr = cmd->cmd_attr_list; attr != NULL; 2684*5184Sek110237 attr = attr->attr_next) { 2685*5184Sek110237 if (attr->attr_name == name) 2686*5184Sek110237 rtn = attr; 2687*5184Sek110237 } 2688*5184Sek110237 2689*5184Sek110237 if (rtn == NULL) 2690*5184Sek110237 return (NULL); 2691*5184Sek110237 2692*5184Sek110237 if (rtn->attr_param_list) { 2693*5184Sek110237 rtn->attr_integer = parser_list2integer(rtn->attr_param_list); 2694*5184Sek110237 } else if (rtn->attr_integer == 0) { 2695*5184Sek110237 rtn->attr_integer = integer_alloc(1); 2696*5184Sek110237 } 2697*5184Sek110237 2698*5184Sek110237 return (rtn); 2699*5184Sek110237 } 2700*5184Sek110237 2701*5184Sek110237 /* 2702*5184Sek110237 * Allocates memory for a list_t structure, initializes it to zero, and 2703*5184Sek110237 * returns a pointer to it. On failure, returns NULL. 2704*5184Sek110237 */ 2705*5184Sek110237 static list_t * 2706*5184Sek110237 alloc_list() 2707*5184Sek110237 { 2708*5184Sek110237 list_t *list; 2709*5184Sek110237 2710*5184Sek110237 if ((list = malloc(sizeof (list_t))) == NULL) { 2711*5184Sek110237 return (NULL); 2712*5184Sek110237 } 2713*5184Sek110237 2714*5184Sek110237 (void) memset(list, 0, sizeof (list_t)); 2715*5184Sek110237 return (list); 2716*5184Sek110237 } 2717*5184Sek110237 2718*5184Sek110237 2719*5184Sek110237 #define USAGE1 \ 2720*5184Sek110237 "Usage:\n" \ 2721*5184Sek110237 "%s: interpret f script and generate file workload\n" \ 2722*5184Sek110237 "Options:\n" \ 2723*5184Sek110237 " [-h] Display verbose help\n" \ 2724*5184Sek110237 " [-p] Disable opening /proc to set uacct to enable truss\n" 2725*5184Sek110237 2726*5184Sek110237 #define PARSER_CMDS \ 2727*5184Sek110237 "create [files|filesets|processes]\n" \ 2728*5184Sek110237 "stats [clear|snap]\n" \ 2729*5184Sek110237 "stats command \"shell command $var1,$var2...\"\n" \ 2730*5184Sek110237 "stats directory <directory>\n" \ 2731*5184Sek110237 "sleep <sleep-value>\n" \ 2732*5184Sek110237 "quit\n\n" \ 2733*5184Sek110237 "Variables:\n" \ 2734*5184Sek110237 "set $var = value\n" \ 2735*5184Sek110237 " $var - regular variables\n" \ 2736*5184Sek110237 " ${var} - internal special variables\n" \ 2737*5184Sek110237 " $(var) - environment variables\n\n" 2738*5184Sek110237 2739*5184Sek110237 #define PARSER_EXAMPLE \ 2740*5184Sek110237 "Example:\n\n" \ 2741*5184Sek110237 "#!/usr/bin/filebench -f\n" \ 2742*5184Sek110237 "\n" \ 2743*5184Sek110237 "define file name=bigfile,path=bigfile,size=1g,prealloc,reuse\n" \ 2744*5184Sek110237 "define process name=randomizer\n" \ 2745*5184Sek110237 "{\n" \ 2746*5184Sek110237 " thread random-thread procname=randomizer\n" \ 2747*5184Sek110237 " {\n" \ 2748*5184Sek110237 " flowop read name=random-read,filename=bigfile,iosize=16k,random\n" \ 2749*5184Sek110237 " }\n" \ 2750*5184Sek110237 "}\n" \ 2751*5184Sek110237 "create files\n" \ 2752*5184Sek110237 "create processes\n" \ 2753*5184Sek110237 "stats clear\n" \ 2754*5184Sek110237 "sleep 30\n" \ 2755*5184Sek110237 "stats snap\n" 2756*5184Sek110237 2757*5184Sek110237 /* 2758*5184Sek110237 * usage() display brief or verbose help for the filebench(1) command. 2759*5184Sek110237 */ 2760*5184Sek110237 static void 2761*5184Sek110237 usage(int help) 2762*5184Sek110237 { 2763*5184Sek110237 if (help >= 1) 2764*5184Sek110237 (void) fprintf(stderr, USAGE1, cmdname); 2765*5184Sek110237 if (help >= 2) { 2766*5184Sek110237 2767*5184Sek110237 (void) fprintf(stderr, 2768*5184Sek110237 "\n'f' language definition:\n\n"); 2769*5184Sek110237 fileobj_usage(); 2770*5184Sek110237 fileset_usage(); 2771*5184Sek110237 procflow_usage(); 2772*5184Sek110237 threadflow_usage(); 2773*5184Sek110237 flowoplib_usage(); 2774*5184Sek110237 eventgen_usage(); 2775*5184Sek110237 (void) fprintf(stderr, PARSER_CMDS); 2776*5184Sek110237 (void) fprintf(stderr, PARSER_EXAMPLE); 2777*5184Sek110237 } 2778*5184Sek110237 exit(E_USAGE); 2779*5184Sek110237 } 2780*5184Sek110237 2781*5184Sek110237 int 2782*5184Sek110237 yywrap() 2783*5184Sek110237 { 2784*5184Sek110237 char buf[1024]; 2785*5184Sek110237 2786*5184Sek110237 if (parentscript) { 2787*5184Sek110237 yyin = parentscript; 2788*5184Sek110237 yy_switchfilescript(yyin); 2789*5184Sek110237 parentscript = NULL; 2790*5184Sek110237 return (0); 2791*5184Sek110237 } else 2792*5184Sek110237 return (1); 2793*5184Sek110237 } 2794