15184Sek110237 25184Sek110237 /* 35184Sek110237 * CDDL HEADER START 45184Sek110237 * 55184Sek110237 * The contents of this file are subject to the terms of the 65184Sek110237 * Common Development and Distribution License (the "License"). 75184Sek110237 * You may not use this file except in compliance with the License. 85184Sek110237 * 95184Sek110237 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 105184Sek110237 * or http://www.opensolaris.org/os/licensing. 115184Sek110237 * See the License for the specific language governing permissions 125184Sek110237 * and limitations under the License. 135184Sek110237 * 145184Sek110237 * When distributing Covered Code, include this CDDL HEADER in each 155184Sek110237 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 165184Sek110237 * If applicable, add the following below this CDDL HEADER, with the 175184Sek110237 * fields enclosed by brackets "[]" replaced with your own identifying 185184Sek110237 * information: Portions Copyright [yyyy] [name of copyright owner] 195184Sek110237 * 205184Sek110237 * CDDL HEADER END 215184Sek110237 */ 225184Sek110237 /* 23*6084Saw148015 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 245184Sek110237 * Use is subject to license terms. 255184Sek110237 */ 265184Sek110237 275184Sek110237 %{ 285184Sek110237 #pragma ident "%Z%%M% %I% %E% SMI" 295184Sek110237 %} 305184Sek110237 315184Sek110237 %{ 325184Sek110237 335184Sek110237 #include <stdlib.h> 345184Sek110237 #include <stdio.h> 355184Sek110237 #include <string.h> 365184Sek110237 #include <signal.h> 375184Sek110237 #include <errno.h> 385184Sek110237 #include <sys/types.h> 395184Sek110237 #include <locale.h> 405184Sek110237 #include <sys/utsname.h> 415184Sek110237 #ifdef HAVE_STDINT_H 425184Sek110237 #include <stdint.h> 435184Sek110237 #endif 445184Sek110237 #include <fcntl.h> 455184Sek110237 #include <sys/mman.h> 465184Sek110237 #include <sys/wait.h> 475184Sek110237 #ifdef HAVE_LIBTECLA 485184Sek110237 #include <libtecla.h> 495184Sek110237 #endif 505184Sek110237 #include "parsertypes.h" 515184Sek110237 #include "filebench.h" 525184Sek110237 #include "utils.h" 535184Sek110237 #include "stats.h" 545184Sek110237 #include "vars.h" 555184Sek110237 #include "eventgen.h" 565184Sek110237 #ifdef HAVE_LIBTECLA 575184Sek110237 #include "auto_comp.h" 585184Sek110237 #endif 595184Sek110237 605184Sek110237 int dofile = FS_FALSE; 615184Sek110237 static const char cmdname[] = "filebench"; 625184Sek110237 static const char cmd_options[] = "pa:f:hi:s:m:"; 635184Sek110237 static void usage(int); 645184Sek110237 655184Sek110237 static cmd_t *cmd = NULL; /* Command being processed */ 665184Sek110237 #ifdef HAVE_LIBTECLA 675184Sek110237 static GetLine *gl; /* GetLine resource object */ 685184Sek110237 #endif 695184Sek110237 705184Sek110237 char *execname; 715184Sek110237 char *fscriptname; 725184Sek110237 int noproc = 0; 735184Sek110237 var_t *var_list = NULL; 745184Sek110237 pidlist_t *pidlist = NULL; 755184Sek110237 char *cwd = NULL; 765184Sek110237 FILE *parentscript = NULL; 775673Saw148015 785673Saw148015 static int filecreate_done = 0; 795673Saw148015 805184Sek110237 /* yacc externals */ 815184Sek110237 extern FILE *yyin; 825184Sek110237 extern int yydebug; 835184Sek110237 extern void yyerror(char *s); 845184Sek110237 855184Sek110237 /* utilities */ 865184Sek110237 static void terminate(void); 875184Sek110237 static cmd_t *alloc_cmd(void); 885184Sek110237 static attr_t *alloc_attr(void); 895184Sek110237 static attr_t *get_attr(cmd_t *cmd, int64_t name); 905184Sek110237 static attr_t *get_attr_integer(cmd_t *cmd, int64_t name); 915184Sek110237 static attr_t *get_attr_bool(cmd_t *cmd, int64_t name); 925184Sek110237 static var_t *alloc_var(void); 935184Sek110237 static var_t *get_var(cmd_t *cmd, int64_t name); 945184Sek110237 static list_t *alloc_list(); 955184Sek110237 965184Sek110237 /* Info Commands */ 975184Sek110237 static void parser_list(cmd_t *); 985184Sek110237 995184Sek110237 /* Define Commands */ 1005184Sek110237 static void parser_proc_define(cmd_t *); 1015184Sek110237 static void parser_thread_define(cmd_t *, procflow_t *, int instances); 1025184Sek110237 static void parser_flowop_define(cmd_t *, threadflow_t *); 1035184Sek110237 static void parser_file_define(cmd_t *); 1045184Sek110237 static void parser_fileset_define(cmd_t *); 1055184Sek110237 1065184Sek110237 /* Create Commands */ 1075184Sek110237 static void parser_proc_create(cmd_t *); 1085184Sek110237 static void parser_thread_create(cmd_t *); 1095184Sek110237 static void parser_flowop_create(cmd_t *); 1105184Sek110237 static void parser_fileset_create(cmd_t *); 1115184Sek110237 1125184Sek110237 /* Shutdown Commands */ 1135184Sek110237 static void parser_proc_shutdown(cmd_t *); 1145184Sek110237 static void parser_filebench_shutdown(cmd_t *cmd); 1155184Sek110237 1165184Sek110237 /* Other Commands */ 1175184Sek110237 static void parser_foreach_integer(cmd_t *cmd); 1185184Sek110237 static void parser_foreach_string(cmd_t *cmd); 1195184Sek110237 static void parser_sleep(cmd_t *cmd); 1205184Sek110237 static void parser_sleep_variable(cmd_t *cmd); 1215184Sek110237 static void parser_log(cmd_t *cmd); 1225184Sek110237 static void parser_statscmd(cmd_t *cmd); 1235184Sek110237 static void parser_statsdump(cmd_t *cmd); 1245184Sek110237 static void parser_statsxmldump(cmd_t *cmd); 1255184Sek110237 static void parser_echo(cmd_t *cmd); 1265184Sek110237 static void parser_usage(cmd_t *cmd); 1275184Sek110237 static void parser_vars(cmd_t *cmd); 1285184Sek110237 static void parser_printvars(cmd_t *cmd); 1295184Sek110237 static void parser_system(cmd_t *cmd); 1305184Sek110237 static void parser_statssnap(cmd_t *cmd); 1315184Sek110237 static void parser_directory(cmd_t *cmd); 1325184Sek110237 static void parser_eventgen(cmd_t *cmd); 1335184Sek110237 static void parser_run(cmd_t *cmd); 1345184Sek110237 static void parser_run_variable(cmd_t *cmd); 1355184Sek110237 static void parser_help(cmd_t *cmd); 1365184Sek110237 static void arg_parse(const char *command); 1375184Sek110237 static void parser_abort(int arg); 1385184Sek110237 1395184Sek110237 %} 1405184Sek110237 1415184Sek110237 %union { 1425184Sek110237 int64_t ival; 1435184Sek110237 uchar_t bval; 1445184Sek110237 char * sval; 1455184Sek110237 fs_u val; 1465184Sek110237 cmd_t *cmd; 1475184Sek110237 attr_t *attr; 1485184Sek110237 list_t *list; 1495184Sek110237 } 1505184Sek110237 1515184Sek110237 %start commands 1525184Sek110237 1535184Sek110237 %token FSC_LIST FSC_DEFINE FSC_EXEC FSC_QUIT FSC_DEBUG FSC_CREATE 1545184Sek110237 %token FSC_SLEEP FSC_STATS FSC_FOREACH FSC_SET FSC_SHUTDOWN FSC_LOG 1555184Sek110237 %token FSC_SYSTEM FSC_FLOWOP FSC_EVENTGEN FSC_ECHO FSC_LOAD FSC_RUN 1565184Sek110237 %token FSC_USAGE FSC_HELP FSC_VARS 1575184Sek110237 %token FSV_STRING FSV_VAL_INT FSV_VAL_BOOLEAN FSV_VARIABLE FSV_WHITESTRING 1585184Sek110237 %token FST_INT FST_BOOLEAN 1595184Sek110237 %token FSE_FILE FSE_PROC FSE_THREAD FSE_CLEAR FSE_ALL FSE_SNAP FSE_DUMP 160*6084Saw148015 %token FSE_DIRECTORY FSE_COMMAND FSE_FILESET FSE_XMLDUMP FSE_MODE 1615184Sek110237 %token FSK_SEPLST FSK_OPENLST FSK_CLOSELST FSK_ASSIGN FSK_IN FSK_QUOTE 1625184Sek110237 %token FSK_DIRSEPLST 1635184Sek110237 %token FSA_SIZE FSA_PREALLOC FSA_PARALLOC FSA_PATH FSA_REUSE 1645184Sek110237 %token FSA_PROCESS FSA_MEMSIZE FSA_RATE FSA_CACHED 1655184Sek110237 %token FSA_IOSIZE FSA_FILE FSA_WSS FSA_NAME FSA_RANDOM FSA_INSTANCES 1665184Sek110237 %token FSA_DSYNC FSA_TARGET FSA_ITERS FSA_NICE FSA_VALUE FSA_BLOCKING 1675184Sek110237 %token FSA_HIGHWATER FSA_DIRECTIO FSA_DIRWIDTH FSA_FD FSA_SRCFD FSA_ROTATEFD 1685184Sek110237 %token FSA_NAMELENGTH FSA_FILESIZE FSA_ENTRIES FSA_FILESIZEGAMMA 169*6084Saw148015 %token FSA_DIRGAMMA FSA_USEISM FSA_ALLDONE FSA_FIRSTDONE FSA_TIMEOUT 1705184Sek110237 1715184Sek110237 %type <ival> FSV_VAL_INT 1725184Sek110237 %type <bval> FSV_VAL_BOOLEAN 1735184Sek110237 %type <sval> FSV_STRING 1745184Sek110237 %type <sval> FSV_WHITESTRING 1755184Sek110237 %type <sval> FSV_VARIABLE 1765184Sek110237 %type <sval> FSK_ASSIGN 1775184Sek110237 1785184Sek110237 %type <ival> FSC_LIST FSC_DEFINE FSC_SET FSC_LOAD FSC_RUN 1795184Sek110237 %type <ival> FSE_FILE FSE_PROC FSE_THREAD FSE_CLEAR FSC_HELP 1805184Sek110237 1815184Sek110237 %type <sval> name 1825184Sek110237 %type <ival> entity 1835184Sek110237 %type <val> value 1845184Sek110237 1855184Sek110237 %type <cmd> command inner_commands load_command run_command 1865184Sek110237 %type <cmd> list_command define_command debug_command create_command 1875184Sek110237 %type <cmd> sleep_command stats_command set_command shutdown_command 1885184Sek110237 %type <cmd> foreach_command log_command system_command flowop_command 1895184Sek110237 %type <cmd> eventgen_command quit_command flowop_list thread_list 1905184Sek110237 %type <cmd> thread echo_command usage_command help_command vars_command 1915184Sek110237 1925184Sek110237 %type <attr> attr_op attr_ops 1935184Sek110237 %type <attr> attr_value 1945184Sek110237 %type <list> integer_seplist string_seplist string_list var_string_list var_string 1955184Sek110237 %type <list> whitevar_string whitevar_string_list 1965184Sek110237 %type <ival> attrs_define_file attrs_define_thread attrs_flowop attrs_define_fileset 1975184Sek110237 %type <ival> attrs_define_proc attrs_eventgen 1985184Sek110237 %type <ival> attr_name 1995184Sek110237 2005184Sek110237 %% 2015184Sek110237 2025184Sek110237 commands: commands command 2035184Sek110237 { 2045184Sek110237 list_t *list = NULL; 2055184Sek110237 list_t *list_end = NULL; 2065184Sek110237 2075184Sek110237 if ($2->cmd != NULL) 2085184Sek110237 $2->cmd($2); 2095184Sek110237 2105184Sek110237 free($2); 2115184Sek110237 } 2125184Sek110237 | commands error 2135184Sek110237 { 2145184Sek110237 if (dofile) 2155184Sek110237 YYABORT; 2165184Sek110237 } 2175184Sek110237 |; 2185184Sek110237 2195184Sek110237 inner_commands: command 2205184Sek110237 { 2215184Sek110237 filebench_log(LOG_DEBUG_IMPL, "inner_command %zx", $1); 2225184Sek110237 $$ = $1; 2235184Sek110237 } 2245184Sek110237 | inner_commands command 2255184Sek110237 { 2265184Sek110237 cmd_t *list = NULL; 2275184Sek110237 cmd_t *list_end = NULL; 2285184Sek110237 2295184Sek110237 /* Find end of list */ 2305184Sek110237 for (list = $1; list != NULL; 2315184Sek110237 list = list->cmd_next) 2325184Sek110237 list_end = list; 2335184Sek110237 2345184Sek110237 list_end->cmd_next = $2; 2355184Sek110237 2365184Sek110237 filebench_log(LOG_DEBUG_IMPL, 2375184Sek110237 "inner_commands adding cmd %zx to list %zx", $2, $1); 2385184Sek110237 2395184Sek110237 $$ = $1; 2405184Sek110237 }; 2415184Sek110237 2425184Sek110237 command: 2435184Sek110237 define_command 2445184Sek110237 | debug_command 2455184Sek110237 | eventgen_command 2465184Sek110237 | create_command 2475184Sek110237 | echo_command 2485184Sek110237 | usage_command 2495184Sek110237 | vars_command 2505184Sek110237 | foreach_command 2515184Sek110237 | help_command 2525184Sek110237 | list_command 2535184Sek110237 | load_command 2545184Sek110237 | log_command 2555184Sek110237 | run_command 2565184Sek110237 | set_command 2575184Sek110237 | shutdown_command 2585184Sek110237 | sleep_command 2595184Sek110237 | stats_command 2605184Sek110237 | system_command 2615184Sek110237 | quit_command; 2625184Sek110237 2635184Sek110237 foreach_command: FSC_FOREACH 2645184Sek110237 { 2655184Sek110237 if (($$ = alloc_cmd()) == NULL) 2665184Sek110237 YYERROR; 2675184Sek110237 filebench_log(LOG_DEBUG_IMPL, "foreach_command %zx", $$); 2685184Sek110237 } 2695184Sek110237 | foreach_command FSV_VARIABLE FSK_IN integer_seplist FSK_OPENLST inner_commands FSK_CLOSELST 2705184Sek110237 { 2715184Sek110237 cmd_t *cmd, *inner_cmd; 2725184Sek110237 list_t *list; 2735184Sek110237 2745184Sek110237 $$ = $1; 2755184Sek110237 $$->cmd_list = $6; 2765184Sek110237 $$->cmd_tgt1 = $2; 2775184Sek110237 $$->cmd_param_list = $4; 2785184Sek110237 $$->cmd = parser_foreach_integer; 2795184Sek110237 2805184Sek110237 for (list = $$->cmd_param_list; list != NULL; 2815184Sek110237 list = list->list_next) { 2825184Sek110237 for (inner_cmd = $$->cmd_list; 2835184Sek110237 inner_cmd != NULL; 2845184Sek110237 inner_cmd = inner_cmd->cmd_next) { 2855184Sek110237 filebench_log(LOG_DEBUG_IMPL, 2865184Sek110237 "packing foreach: %zx %s=%lld, cmd %zx", 2875184Sek110237 $$, 2885184Sek110237 $$->cmd_tgt1, 2895184Sek110237 *list->list_integer, inner_cmd); 2905184Sek110237 } 2915184Sek110237 } 2925184Sek110237 }| foreach_command FSV_VARIABLE FSK_IN string_seplist FSK_OPENLST inner_commands FSK_CLOSELST 2935184Sek110237 { 2945184Sek110237 cmd_t *cmd, *inner_cmd; 2955184Sek110237 list_t *list; 2965184Sek110237 2975184Sek110237 $$ = $1; 2985184Sek110237 $$->cmd_list = $6; 2995184Sek110237 $$->cmd_tgt1 = $2; 3005184Sek110237 $$->cmd_param_list = $4; 3015184Sek110237 $$->cmd = parser_foreach_string; 3025184Sek110237 3035184Sek110237 for (list = $$->cmd_param_list; list != NULL; 3045184Sek110237 list = list->list_next) { 3055184Sek110237 for (inner_cmd = $$->cmd_list; 3065184Sek110237 inner_cmd != NULL; 3075184Sek110237 inner_cmd = inner_cmd->cmd_next) { 3085184Sek110237 filebench_log(LOG_DEBUG_IMPL, 3095184Sek110237 "packing foreach: %zx %s=%s, cmd %zx", 3105184Sek110237 $$, 3115184Sek110237 $$->cmd_tgt1, 3125184Sek110237 *list->list_string, inner_cmd); 3135184Sek110237 } 3145184Sek110237 } 3155184Sek110237 }; 3165184Sek110237 3175184Sek110237 integer_seplist: FSV_VAL_INT 3185184Sek110237 { 3195184Sek110237 if (($$ = alloc_list()) == NULL) 3205184Sek110237 YYERROR; 3215184Sek110237 3225184Sek110237 $$->list_integer = integer_alloc($1); 3235184Sek110237 } 3245184Sek110237 | integer_seplist FSK_SEPLST FSV_VAL_INT 3255184Sek110237 { 3265184Sek110237 list_t *list = NULL; 3275184Sek110237 list_t *list_end = NULL; 3285184Sek110237 3295184Sek110237 if (($$ = alloc_list()) == NULL) 3305184Sek110237 YYERROR; 3315184Sek110237 3325184Sek110237 $$->list_integer = integer_alloc($3); 3335184Sek110237 3345184Sek110237 /* Find end of list */ 3355184Sek110237 for (list = $1; list != NULL; 3365184Sek110237 list = list->list_next) 3375184Sek110237 list_end = list; 3385184Sek110237 list_end->list_next = $$; 3395184Sek110237 $$ = $1; 3405184Sek110237 }; 3415184Sek110237 3425184Sek110237 string_seplist: FSK_QUOTE FSV_WHITESTRING FSK_QUOTE 3435184Sek110237 { 3445184Sek110237 if (($$ = alloc_list()) == NULL) 3455184Sek110237 YYERROR; 3465184Sek110237 3475184Sek110237 $$->list_string = string_alloc($2); 3485184Sek110237 } 3495184Sek110237 | string_seplist FSK_SEPLST FSK_QUOTE FSV_WHITESTRING FSK_QUOTE 3505184Sek110237 { 3515184Sek110237 list_t *list = NULL; 3525184Sek110237 list_t *list_end = NULL; 3535184Sek110237 3545184Sek110237 if (($$ = alloc_list()) == NULL) 3555184Sek110237 YYERROR; 3565184Sek110237 3575184Sek110237 $$->list_string = string_alloc($4); 3585184Sek110237 3595184Sek110237 /* Find end of list */ 3605184Sek110237 for (list = $1; list != NULL; 3615184Sek110237 list = list->list_next) 3625184Sek110237 list_end = list; 3635184Sek110237 list_end->list_next = $$; 3645184Sek110237 $$ = $1; 3655184Sek110237 }; 3665184Sek110237 3675184Sek110237 eventgen_command: FSC_EVENTGEN 3685184Sek110237 { 3695184Sek110237 if (($$ = alloc_cmd()) == NULL) 3705184Sek110237 YYERROR; 3715184Sek110237 $$->cmd = &parser_eventgen; 3725184Sek110237 } 3735184Sek110237 | eventgen_command attr_ops 3745184Sek110237 { 3755184Sek110237 $1->cmd_attr_list = $2; 3765184Sek110237 }; 3775184Sek110237 3785184Sek110237 system_command: FSC_SYSTEM whitevar_string_list 3795184Sek110237 { 3805184Sek110237 if (($$ = alloc_cmd()) == NULL) 3815184Sek110237 YYERROR; 3825184Sek110237 3835184Sek110237 $$->cmd_param_list = $2; 3845184Sek110237 $$->cmd = parser_system; 3855184Sek110237 }; 3865184Sek110237 3875184Sek110237 echo_command: FSC_ECHO whitevar_string_list 3885184Sek110237 { 3895184Sek110237 if (($$ = alloc_cmd()) == NULL) 3905184Sek110237 YYERROR; 3915184Sek110237 3925184Sek110237 $$->cmd_param_list = $2; 3935184Sek110237 $$->cmd = parser_echo; 3945184Sek110237 }; 3955184Sek110237 3965184Sek110237 usage_command: FSC_USAGE whitevar_string_list 3975184Sek110237 { 3985184Sek110237 if (($$ = alloc_cmd()) == NULL) 3995184Sek110237 YYERROR; 4005184Sek110237 4015184Sek110237 $$->cmd_param_list = $2; 4025184Sek110237 $$->cmd = parser_usage; 4035184Sek110237 }; 4045184Sek110237 4055184Sek110237 vars_command: FSC_VARS 4065184Sek110237 { 4075184Sek110237 if (($$ = alloc_cmd()) == NULL) 4085184Sek110237 YYERROR; 4095184Sek110237 4105184Sek110237 $$->cmd = parser_printvars; 4115184Sek110237 }; 4125184Sek110237 4135184Sek110237 string_list: FSV_VARIABLE 4145184Sek110237 { 4155184Sek110237 if (($$ = alloc_list()) == NULL) 4165184Sek110237 YYERROR; 4175184Sek110237 4185184Sek110237 $$->list_string = string_alloc($1); 4195184Sek110237 } 4205184Sek110237 | string_list FSK_SEPLST FSV_VARIABLE 4215184Sek110237 { 4225184Sek110237 list_t *list = NULL; 4235184Sek110237 list_t *list_end = NULL; 4245184Sek110237 4255184Sek110237 if (($$ = alloc_list()) == NULL) 4265184Sek110237 YYERROR; 4275184Sek110237 4285184Sek110237 $$->list_string = string_alloc($3); 4295184Sek110237 4305184Sek110237 /* Find end of list */ 4315184Sek110237 for (list = $1; list != NULL; 4325184Sek110237 list = list->list_next) 4335184Sek110237 list_end = list; 4345184Sek110237 list_end->list_next = $$; 4355184Sek110237 $$ = $1; 4365184Sek110237 }; 4375184Sek110237 4385184Sek110237 var_string: FSV_VARIABLE 4395184Sek110237 { 4405184Sek110237 if (($$ = alloc_list()) == NULL) 4415184Sek110237 YYERROR; 4425184Sek110237 4435184Sek110237 $$->list_string = string_alloc($1); 4445184Sek110237 } 4455184Sek110237 | FSV_STRING 4465184Sek110237 { 4475184Sek110237 if (($$ = alloc_list()) == NULL) 4485184Sek110237 YYERROR; 4495184Sek110237 4505184Sek110237 $$->list_string = string_alloc($1); 4515184Sek110237 }; 4525184Sek110237 4535184Sek110237 var_string_list: var_string 4545184Sek110237 { 4555184Sek110237 $$ = $1; 4565184Sek110237 }| var_string FSV_STRING 4575184Sek110237 { 4585184Sek110237 list_t *list = NULL; 4595184Sek110237 list_t *list_end = NULL; 4605184Sek110237 4615184Sek110237 /* Add string */ 4625184Sek110237 if (($$ = alloc_list()) == NULL) 4635184Sek110237 YYERROR; 4645184Sek110237 4655184Sek110237 $$->list_string = string_alloc($2); 4665184Sek110237 4675184Sek110237 /* Find end of list */ 4685184Sek110237 for (list = $1; list != NULL; 4695184Sek110237 list = list->list_next) 4705184Sek110237 list_end = list; 4715184Sek110237 list_end->list_next = $$; 4725184Sek110237 $$ = $1; 4735184Sek110237 4745184Sek110237 }| var_string FSV_VARIABLE 4755184Sek110237 { 4765184Sek110237 list_t *list = NULL; 4775184Sek110237 list_t *list_end = NULL; 4785184Sek110237 4795184Sek110237 /* Add variable */ 4805184Sek110237 if (($$ = alloc_list()) == NULL) 4815184Sek110237 YYERROR; 4825184Sek110237 4835184Sek110237 $$->list_string = string_alloc($2); 4845184Sek110237 4855184Sek110237 /* Find end of list */ 4865184Sek110237 for (list = $1; list != NULL; 4875184Sek110237 list = list->list_next) 4885184Sek110237 list_end = list; 4895184Sek110237 list_end->list_next = $$; 4905184Sek110237 $$ = $1; 4915184Sek110237 } |var_string_list FSV_STRING 4925184Sek110237 { 4935184Sek110237 list_t *list = NULL; 4945184Sek110237 list_t *list_end = NULL; 4955184Sek110237 4965184Sek110237 /* Add string */ 4975184Sek110237 if (($$ = alloc_list()) == NULL) 4985184Sek110237 YYERROR; 4995184Sek110237 5005184Sek110237 $$->list_string = string_alloc($2); 5015184Sek110237 5025184Sek110237 /* Find end of list */ 5035184Sek110237 for (list = $1; list != NULL; 5045184Sek110237 list = list->list_next) 5055184Sek110237 list_end = list; 5065184Sek110237 list_end->list_next = $$; 5075184Sek110237 $$ = $1; 5085184Sek110237 5095184Sek110237 }| var_string_list FSV_VARIABLE 5105184Sek110237 { 5115184Sek110237 list_t *list = NULL; 5125184Sek110237 list_t *list_end = NULL; 5135184Sek110237 5145184Sek110237 /* Add variable */ 5155184Sek110237 if (($$ = alloc_list()) == NULL) 5165184Sek110237 YYERROR; 5175184Sek110237 5185184Sek110237 $$->list_string = string_alloc($2); 5195184Sek110237 5205184Sek110237 /* Find end of list */ 5215184Sek110237 for (list = $1; list != NULL; 5225184Sek110237 list = list->list_next) 5235184Sek110237 list_end = list; 5245184Sek110237 list_end->list_next = $$; 5255184Sek110237 $$ = $1; 5265184Sek110237 }; 5275184Sek110237 5285184Sek110237 whitevar_string: FSK_QUOTE FSV_VARIABLE 5295184Sek110237 { 5305184Sek110237 if (($$ = alloc_list()) == NULL) 5315184Sek110237 YYERROR; 5325184Sek110237 5335184Sek110237 $$->list_string = string_alloc($2); 5345184Sek110237 } 5355184Sek110237 | FSK_QUOTE FSV_WHITESTRING 5365184Sek110237 { 5375184Sek110237 if (($$ = alloc_list()) == NULL) 5385184Sek110237 YYERROR; 5395184Sek110237 5405184Sek110237 $$->list_string = string_alloc($2); 5415184Sek110237 }; 5425184Sek110237 5435184Sek110237 whitevar_string_list: whitevar_string FSV_WHITESTRING 5445184Sek110237 { 5455184Sek110237 list_t *list = NULL; 5465184Sek110237 list_t *list_end = NULL; 5475184Sek110237 5485184Sek110237 /* Add string */ 5495184Sek110237 if (($$ = alloc_list()) == NULL) 5505184Sek110237 YYERROR; 5515184Sek110237 5525184Sek110237 $$->list_string = string_alloc($2); 5535184Sek110237 5545184Sek110237 /* Find end of list */ 5555184Sek110237 for (list = $1; list != NULL; 5565184Sek110237 list = list->list_next) 5575184Sek110237 list_end = list; 5585184Sek110237 list_end->list_next = $$; 5595184Sek110237 $$ = $1; 5605184Sek110237 5615184Sek110237 }| whitevar_string FSV_VARIABLE 5625184Sek110237 { 5635184Sek110237 list_t *list = NULL; 5645184Sek110237 list_t *list_end = NULL; 5655184Sek110237 5665184Sek110237 /* Add variable */ 5675184Sek110237 if (($$ = alloc_list()) == NULL) 5685184Sek110237 YYERROR; 5695184Sek110237 5705184Sek110237 $$->list_string = string_alloc($2); 5715184Sek110237 5725184Sek110237 /* Find end of list */ 5735184Sek110237 for (list = $1; list != NULL; 5745184Sek110237 list = list->list_next) 5755184Sek110237 list_end = list; 5765184Sek110237 list_end->list_next = $$; 5775184Sek110237 $$ = $1; 5785184Sek110237 } |whitevar_string_list FSV_WHITESTRING 5795184Sek110237 { 5805184Sek110237 list_t *list = NULL; 5815184Sek110237 list_t *list_end = NULL; 5825184Sek110237 5835184Sek110237 /* Add string */ 5845184Sek110237 if (($$ = alloc_list()) == NULL) 5855184Sek110237 YYERROR; 5865184Sek110237 5875184Sek110237 $$->list_string = string_alloc($2); 5885184Sek110237 5895184Sek110237 /* Find end of list */ 5905184Sek110237 for (list = $1; list != NULL; 5915184Sek110237 list = list->list_next) 5925184Sek110237 list_end = list; 5935184Sek110237 list_end->list_next = $$; 5945184Sek110237 $$ = $1; 5955184Sek110237 5965184Sek110237 }| whitevar_string_list FSV_VARIABLE 5975184Sek110237 { 5985184Sek110237 list_t *list = NULL; 5995184Sek110237 list_t *list_end = NULL; 6005184Sek110237 6015184Sek110237 /* Add variable */ 6025184Sek110237 if (($$ = alloc_list()) == NULL) 6035184Sek110237 YYERROR; 6045184Sek110237 6055184Sek110237 $$->list_string = string_alloc($2); 6065184Sek110237 6075184Sek110237 /* Find end of list */ 6085184Sek110237 for (list = $1; list != NULL; 6095184Sek110237 list = list->list_next) 6105184Sek110237 list_end = list; 6115184Sek110237 list_end->list_next = $$; 6125184Sek110237 $$ = $1; 6135184Sek110237 }| whitevar_string_list FSK_QUOTE 6145184Sek110237 { 6155184Sek110237 $$ = $1; 6165184Sek110237 }| whitevar_string FSK_QUOTE 6175184Sek110237 { 6185184Sek110237 $$ = $1; 6195184Sek110237 }; 6205184Sek110237 6215184Sek110237 list_command: FSC_LIST 6225184Sek110237 { 6235184Sek110237 if (($$ = alloc_cmd()) == NULL) 6245184Sek110237 YYERROR; 6255184Sek110237 $$->cmd = &parser_list; 6265184Sek110237 }; 6275184Sek110237 6285184Sek110237 log_command: FSC_LOG whitevar_string_list 6295184Sek110237 { 6305184Sek110237 if (($$ = alloc_cmd()) == NULL) 6315184Sek110237 YYERROR; 6325184Sek110237 $$->cmd = &parser_log; 6335184Sek110237 $$->cmd_param_list = $2; 6345184Sek110237 }; 6355184Sek110237 6365184Sek110237 debug_command: FSC_DEBUG FSV_VAL_INT 6375184Sek110237 { 6385184Sek110237 if (($$ = alloc_cmd()) == NULL) 6395184Sek110237 YYERROR; 6405184Sek110237 $$->cmd = NULL; 6415184Sek110237 filebench_shm->debug_level = $2; 6425184Sek110237 if (filebench_shm->debug_level > 9) 6435184Sek110237 yydebug = 1; 6445184Sek110237 }; 6455184Sek110237 6465184Sek110237 set_command: FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_VAL_INT 6475184Sek110237 { 6485184Sek110237 if (($$ = alloc_cmd()) == NULL) 6495184Sek110237 YYERROR; 6505184Sek110237 var_assign_integer($2, $4); 6515184Sek110237 if (parentscript) { 6525184Sek110237 $$->cmd_tgt1 = $2; 6535184Sek110237 parser_vars($$); 6545184Sek110237 } 6555184Sek110237 $$->cmd = NULL; 6565184Sek110237 } 6575184Sek110237 | FSC_SET FSV_VARIABLE FSK_ASSIGN FSK_QUOTE FSV_WHITESTRING FSK_QUOTE 6585184Sek110237 { 6595184Sek110237 if (($$ = alloc_cmd()) == NULL) 6605184Sek110237 YYERROR; 6615184Sek110237 var_assign_string($2, $5); 6625184Sek110237 if (parentscript) { 6635184Sek110237 $$->cmd_tgt1 = $2; 6645184Sek110237 parser_vars($$); 6655184Sek110237 } 6665184Sek110237 $$->cmd = NULL; 6675184Sek110237 }| FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_STRING 6685184Sek110237 { 6695184Sek110237 if (($$ = alloc_cmd()) == NULL) 6705184Sek110237 YYERROR; 6715184Sek110237 var_assign_string($2, $4); 6725184Sek110237 if (parentscript) { 6735184Sek110237 $$->cmd_tgt1 = $2; 6745184Sek110237 parser_vars($$); 6755184Sek110237 } 6765184Sek110237 $$->cmd = NULL; 6775184Sek110237 }| FSC_SET FSV_VARIABLE FSK_ASSIGN FSV_VARIABLE 6785184Sek110237 { 6795184Sek110237 if (($$ = alloc_cmd()) == NULL) 6805184Sek110237 YYERROR; 6815184Sek110237 var_assign_var($2, $4); 6825184Sek110237 if (parentscript) { 6835184Sek110237 $$->cmd_tgt1 = $2; 6845184Sek110237 parser_vars($$); 6855184Sek110237 } 6865184Sek110237 $$->cmd = NULL; 687*6084Saw148015 } | FSC_SET FSE_MODE FSC_QUIT FSA_TIMEOUT 688*6084Saw148015 { 689*6084Saw148015 filebench_shm->shm_rmode = FILEBENCH_MODE_TIMEOUT; 690*6084Saw148015 if (($$ = alloc_cmd()) == NULL) 691*6084Saw148015 YYERROR; 692*6084Saw148015 $$->cmd = NULL; 693*6084Saw148015 } | FSC_SET FSE_MODE FSC_QUIT FSA_ALLDONE 694*6084Saw148015 { 695*6084Saw148015 filebench_shm->shm_rmode = FILEBENCH_MODE_QALLDONE; 696*6084Saw148015 if (($$ = alloc_cmd()) == NULL) 697*6084Saw148015 YYERROR; 698*6084Saw148015 $$->cmd = NULL; 699*6084Saw148015 } | FSC_SET FSE_MODE FSC_QUIT FSA_FIRSTDONE 700*6084Saw148015 { 701*6084Saw148015 filebench_shm->shm_rmode = FILEBENCH_MODE_Q1STDONE; 702*6084Saw148015 if (($$ = alloc_cmd()) == NULL) 703*6084Saw148015 YYERROR; 704*6084Saw148015 $$->cmd = NULL; 7055184Sek110237 }; 7065184Sek110237 7075184Sek110237 stats_command: FSC_STATS FSE_SNAP 7085184Sek110237 { 7095184Sek110237 if (($$ = alloc_cmd()) == NULL) 7105184Sek110237 YYERROR; 7115184Sek110237 $$->cmd = (void (*)(struct cmd *))&parser_statssnap; 7125184Sek110237 break; 7135184Sek110237 7145184Sek110237 } 7155184Sek110237 | FSC_STATS FSE_CLEAR 7165184Sek110237 { 7175184Sek110237 if (($$ = alloc_cmd()) == NULL) 7185184Sek110237 YYERROR; 7195184Sek110237 $$->cmd = (void (*)(struct cmd *))&stats_clear; 7205184Sek110237 7215184Sek110237 } 7225184Sek110237 | FSC_STATS FSE_DIRECTORY var_string_list 7235184Sek110237 { 7245184Sek110237 if (($$ = alloc_cmd()) == NULL) 7255184Sek110237 YYERROR; 7265184Sek110237 $$->cmd_param_list = $3; 7275184Sek110237 $$->cmd = (void (*)(struct cmd *))&parser_directory; 7285184Sek110237 7295184Sek110237 } 7305184Sek110237 | FSC_STATS FSE_COMMAND whitevar_string_list 7315184Sek110237 { 7325184Sek110237 if (($$ = alloc_cmd()) == NULL) 7335184Sek110237 YYERROR; 7345184Sek110237 7355184Sek110237 $$->cmd_param_list = $3; 7365184Sek110237 $$->cmd = parser_statscmd; 7375184Sek110237 7385184Sek110237 }| FSC_STATS FSE_DUMP whitevar_string_list 7395184Sek110237 { 7405184Sek110237 if (($$ = alloc_cmd()) == NULL) 7415184Sek110237 YYERROR; 7425184Sek110237 7435184Sek110237 $$->cmd_param_list = $3; 7445184Sek110237 $$->cmd = parser_statsdump; 7455184Sek110237 }| FSC_STATS FSE_XMLDUMP whitevar_string_list 7465184Sek110237 { 7475184Sek110237 if (($$ = alloc_cmd()) == NULL) 7485184Sek110237 YYERROR; 7495184Sek110237 7505184Sek110237 $$->cmd_param_list = $3; 7515184Sek110237 $$->cmd = parser_statsxmldump; 7525184Sek110237 }; 7535184Sek110237 7545184Sek110237 quit_command: FSC_QUIT 7555184Sek110237 { 7565184Sek110237 if (($$ = alloc_cmd()) == NULL) 7575184Sek110237 YYERROR; 7585184Sek110237 $$->cmd = parser_filebench_shutdown; 7595184Sek110237 }; 7605184Sek110237 7615184Sek110237 flowop_list: flowop_command 7625184Sek110237 { 7635184Sek110237 $$ = $1; 7645184Sek110237 }| flowop_list flowop_command 7655184Sek110237 { 7665184Sek110237 cmd_t *list = NULL; 7675184Sek110237 cmd_t *list_end = NULL; 7685184Sek110237 7695184Sek110237 /* Find end of list */ 7705184Sek110237 for (list = $1; list != NULL; 7715184Sek110237 list = list->cmd_next) 7725184Sek110237 list_end = list; 7735184Sek110237 7745184Sek110237 list_end->cmd_next = $2; 7755184Sek110237 7765184Sek110237 filebench_log(LOG_DEBUG_IMPL, 7775184Sek110237 "flowop_list adding cmd %zx to list %zx", $2, $1); 7785184Sek110237 7795184Sek110237 $$ = $1; 7805184Sek110237 }; 7815184Sek110237 7825184Sek110237 thread: FSE_THREAD attr_ops FSK_OPENLST flowop_list FSK_CLOSELST 7835184Sek110237 { 7845184Sek110237 /* 7855184Sek110237 * Allocate a cmd node per thread, with a 7865184Sek110237 * list of flowops attached to the cmd_list 7875184Sek110237 */ 7885184Sek110237 if (($$ = alloc_cmd()) == NULL) 7895184Sek110237 YYERROR; 7905184Sek110237 $$->cmd_list = $4; 7915184Sek110237 $$->cmd_attr_list = $2; 7925184Sek110237 }; 7935184Sek110237 7945184Sek110237 thread_list: thread 7955184Sek110237 { 7965184Sek110237 $$ = $1; 7975184Sek110237 }| thread_list thread 7985184Sek110237 { 7995184Sek110237 cmd_t *list = NULL; 8005184Sek110237 cmd_t *list_end = NULL; 8015184Sek110237 8025184Sek110237 /* Find end of list */ 8035184Sek110237 for (list = $1; list != NULL; 8045184Sek110237 list = list->cmd_next) 8055184Sek110237 list_end = list; 8065184Sek110237 8075184Sek110237 list_end->cmd_next = $2; 8085184Sek110237 8095184Sek110237 filebench_log(LOG_DEBUG_IMPL, 8105184Sek110237 "thread_list adding cmd %zx to list %zx", $2, $1); 8115184Sek110237 8125184Sek110237 $$ = $1; 8135184Sek110237 }; 8145184Sek110237 8155184Sek110237 define_command: FSC_DEFINE FSE_PROC attr_ops FSK_OPENLST thread_list FSK_CLOSELST 8165184Sek110237 { 8175184Sek110237 if (($$ = alloc_cmd()) == NULL) 8185184Sek110237 YYERROR; 8195184Sek110237 $$->cmd = &parser_proc_define; 8205184Sek110237 $$->cmd_list = $5; 8215184Sek110237 $$->cmd_attr_list = $3; 8225184Sek110237 8235184Sek110237 }| FSC_DEFINE FSE_FILE 8245184Sek110237 { 8255184Sek110237 if (($$ = alloc_cmd()) == NULL) 8265184Sek110237 YYERROR; 8275184Sek110237 $$->cmd = &parser_file_define; 8285184Sek110237 }| FSC_DEFINE FSE_FILESET 8295184Sek110237 { 8305184Sek110237 if (($$ = alloc_cmd()) == NULL) 8315184Sek110237 YYERROR; 8325184Sek110237 $$->cmd = &parser_fileset_define; 8335184Sek110237 } 8345184Sek110237 | define_command attr_ops 8355184Sek110237 { 8365184Sek110237 $1->cmd_attr_list = $2; 8375184Sek110237 }; 8385184Sek110237 8395184Sek110237 create_command: FSC_CREATE entity 8405184Sek110237 { 8415184Sek110237 if (($$ = alloc_cmd()) == NULL) 8425184Sek110237 YYERROR; 8435184Sek110237 switch ($2) { 8445184Sek110237 case FSE_PROC: 8455184Sek110237 $$->cmd = &parser_proc_create; 8465184Sek110237 break; 8475673Saw148015 case FSE_FILESET: 8485184Sek110237 case FSE_FILE: 8495184Sek110237 $$->cmd = &parser_fileset_create; 8505184Sek110237 break; 8515184Sek110237 default: 8525184Sek110237 filebench_log(LOG_ERROR, "unknown entity", $2); 8535184Sek110237 YYERROR; 8545184Sek110237 } 8555184Sek110237 8565184Sek110237 }; 8575184Sek110237 8585184Sek110237 shutdown_command: FSC_SHUTDOWN entity 8595184Sek110237 { 8605184Sek110237 if (($$ = alloc_cmd()) == NULL) 8615184Sek110237 YYERROR; 8625184Sek110237 switch ($2) { 8635184Sek110237 case FSE_PROC: 8645184Sek110237 $$->cmd = &parser_proc_shutdown; 8655184Sek110237 break; 8665184Sek110237 default: 8675184Sek110237 filebench_log(LOG_ERROR, "unknown entity", $2); 8685184Sek110237 YYERROR; 8695184Sek110237 } 8705184Sek110237 8715184Sek110237 }; 8725184Sek110237 8735184Sek110237 sleep_command: FSC_SLEEP FSV_VAL_INT 8745184Sek110237 { 8755184Sek110237 if (($$ = alloc_cmd()) == NULL) 8765184Sek110237 YYERROR; 8775184Sek110237 $$->cmd = parser_sleep; 8785184Sek110237 $$->cmd_qty = $2; 8795184Sek110237 } 8805184Sek110237 | FSC_SLEEP FSV_VARIABLE 8815184Sek110237 { 8825184Sek110237 vinteger_t *integer; 8835184Sek110237 8845184Sek110237 if (($$ = alloc_cmd()) == NULL) 8855184Sek110237 YYERROR; 8865184Sek110237 $$->cmd = parser_sleep_variable; 8875184Sek110237 $$->cmd_tgt1 = fb_stralloc($2); 8885184Sek110237 }; 8895184Sek110237 8905184Sek110237 run_command: FSC_RUN FSV_VAL_INT 8915184Sek110237 { 8925184Sek110237 if (($$ = alloc_cmd()) == NULL) 8935184Sek110237 YYERROR; 8945184Sek110237 $$->cmd = parser_run; 8955184Sek110237 $$->cmd_qty = $2; 8965184Sek110237 } 8975184Sek110237 | FSC_RUN FSV_VARIABLE 8985184Sek110237 { 8995184Sek110237 vinteger_t *integer; 9005184Sek110237 9015184Sek110237 if (($$ = alloc_cmd()) == NULL) 9025184Sek110237 YYERROR; 9035184Sek110237 $$->cmd = parser_run_variable; 9045184Sek110237 $$->cmd_tgt1 = fb_stralloc($2); 9055184Sek110237 } 9065184Sek110237 | FSC_RUN 9075184Sek110237 { 9085184Sek110237 vinteger_t *integer; 9095184Sek110237 9105184Sek110237 if (($$ = alloc_cmd()) == NULL) 9115184Sek110237 YYERROR; 9125184Sek110237 $$->cmd = parser_run; 9135184Sek110237 $$->cmd_qty = 60UL; 9145184Sek110237 }; 9155184Sek110237 9165184Sek110237 help_command: FSC_HELP 9175184Sek110237 { 9185184Sek110237 if (($$ = alloc_cmd()) == NULL) 9195184Sek110237 YYERROR; 9205184Sek110237 $$->cmd = parser_help; 9215184Sek110237 }; 9225184Sek110237 9235184Sek110237 flowop_command: FSC_FLOWOP name 9245184Sek110237 { 9255184Sek110237 if (($$ = alloc_cmd()) == NULL) 9265184Sek110237 YYERROR; 9275184Sek110237 $$->cmd_name = fb_stralloc($2); 9285184Sek110237 } 9295184Sek110237 | flowop_command attr_ops 9305184Sek110237 { 9315184Sek110237 $1->cmd_attr_list = $2; 9325184Sek110237 }; 9335184Sek110237 9345184Sek110237 load_command: FSC_LOAD FSV_STRING 9355184Sek110237 { 9365184Sek110237 FILE *newfile; 9375184Sek110237 char loadfile[128]; 9385184Sek110237 9395184Sek110237 if (($$ = alloc_cmd()) == NULL) 9405184Sek110237 YYERROR; 9415184Sek110237 9425184Sek110237 (void) strcpy(loadfile, $2); 9435184Sek110237 (void) strcat(loadfile, ".f"); 9445184Sek110237 9455184Sek110237 if ((newfile = fopen(loadfile, "r")) == NULL) { 9465184Sek110237 (void) strcpy(loadfile, FILEBENCHDIR); 9475184Sek110237 (void) strcat(loadfile, "/workloads/"); 9485184Sek110237 (void) strcat(loadfile, $2); 9495184Sek110237 (void) strcat(loadfile, ".f"); 9505184Sek110237 if ((newfile = fopen(loadfile, "r")) == NULL) { 9515184Sek110237 filebench_log(LOG_ERROR, "Cannot open %s", loadfile); 9525184Sek110237 YYERROR; 9535184Sek110237 } 9545184Sek110237 } 9555184Sek110237 9565184Sek110237 parentscript = yyin; 9575184Sek110237 yyin = newfile; 9585184Sek110237 yy_switchfileparent(yyin); 9595184Sek110237 }; 9605184Sek110237 9615184Sek110237 entity: FSE_PROC {$$ = FSE_PROC;} 9625184Sek110237 | FSE_THREAD {$$ = FSE_THREAD;} 9635184Sek110237 | FSE_FILESET {$$ = FSE_FILESET;} 9645184Sek110237 | FSE_FILE {$$ = FSE_FILE;}; 9655184Sek110237 9665184Sek110237 value: FSV_VAL_INT { $$.i = $1;} 9675184Sek110237 | FSV_STRING { $$.s = $1;} 9685184Sek110237 | FSV_VAL_BOOLEAN { $$.b = $1;}; 9695184Sek110237 9705184Sek110237 name: FSV_STRING; 9715184Sek110237 9725184Sek110237 attr_ops: attr_op 9735184Sek110237 { 9745184Sek110237 $$ = $1; 9755184Sek110237 } 9765184Sek110237 | attr_ops FSK_SEPLST attr_op 9775184Sek110237 { 9785184Sek110237 attr_t *attr = NULL; 9795184Sek110237 attr_t *list_end = NULL; 9805184Sek110237 9815184Sek110237 for (attr = $1; attr != NULL; 9825184Sek110237 attr = attr->attr_next) 9835184Sek110237 list_end = attr; /* Find end of list */ 9845184Sek110237 9855184Sek110237 list_end->attr_next = $3; 9865184Sek110237 9875184Sek110237 $$ = $1; 9885184Sek110237 }; 9895184Sek110237 9905184Sek110237 attr_op: attr_name FSK_ASSIGN attr_value 9915184Sek110237 { 9925184Sek110237 $$ = $3; 9935184Sek110237 $$->attr_name = $1; 9945184Sek110237 } 9955184Sek110237 | attr_name 9965184Sek110237 { 9975184Sek110237 if (($$ = alloc_attr()) == NULL) 9985184Sek110237 YYERROR; 9995184Sek110237 $$->attr_name = $1; 10005184Sek110237 } 10015184Sek110237 10025184Sek110237 attr_name: attrs_define_file 10035184Sek110237 |attrs_define_fileset 10045184Sek110237 |attrs_define_thread 10055184Sek110237 |attrs_define_proc 10065184Sek110237 |attrs_flowop 10075184Sek110237 |attrs_eventgen; 10085184Sek110237 10095184Sek110237 attrs_define_proc: 10105184Sek110237 FSA_NICE { $$ = FSA_NICE;} 10115184Sek110237 |FSA_INSTANCES { $$ = FSA_INSTANCES;}; 10125184Sek110237 10135184Sek110237 attrs_define_file: 10145184Sek110237 FSA_SIZE { $$ = FSA_SIZE;} 10155184Sek110237 | FSA_PATH { $$ = FSA_PATH;} 10165184Sek110237 | FSA_REUSE { $$ = FSA_REUSE;} 10175184Sek110237 | FSA_PREALLOC { $$ = FSA_PREALLOC;} 10185184Sek110237 | FSA_PARALLOC { $$ = FSA_PARALLOC;}; 10195184Sek110237 10205184Sek110237 attrs_define_fileset: 10215184Sek110237 FSA_SIZE { $$ = FSA_SIZE;} 10225184Sek110237 | FSA_PATH { $$ = FSA_PATH;} 10235184Sek110237 | FSA_DIRWIDTH { $$ = FSA_DIRWIDTH;} 10245184Sek110237 | FSA_PREALLOC { $$ = FSA_PREALLOC;} 10255184Sek110237 | FSA_FILESIZEGAMMA { $$ = FSA_FILESIZEGAMMA;} 10265184Sek110237 | FSA_DIRGAMMA { $$ = FSA_DIRGAMMA;} 10275184Sek110237 | FSA_CACHED { $$ = FSA_CACHED;} 10285184Sek110237 | FSA_ENTRIES { $$ = FSA_ENTRIES;}; 10295184Sek110237 10305184Sek110237 attrs_define_thread: 10315184Sek110237 FSA_PROCESS { $$ = FSA_PROCESS;} 10325184Sek110237 |FSA_MEMSIZE { $$ = FSA_MEMSIZE;} 10335184Sek110237 |FSA_USEISM { $$ = FSA_USEISM;} 10345184Sek110237 |FSA_INSTANCES { $$ = FSA_INSTANCES;}; 10355184Sek110237 10365184Sek110237 attrs_flowop: 10375184Sek110237 FSA_WSS { $$ = FSA_WSS;} 10385184Sek110237 |FSA_FILE { $$ = FSA_FILE;} 10395184Sek110237 |FSA_NAME { $$ = FSA_NAME;} 10405184Sek110237 |FSA_RANDOM { $$ = FSA_RANDOM;} 10415184Sek110237 |FSA_FD { $$ = FSA_FD;} 10425184Sek110237 |FSA_SRCFD { $$ = FSA_SRCFD;} 10435184Sek110237 |FSA_ROTATEFD { $$ = FSA_ROTATEFD;} 10445184Sek110237 |FSA_DSYNC { $$ = FSA_DSYNC;} 10455184Sek110237 |FSA_DIRECTIO { $$ = FSA_DIRECTIO;} 10465184Sek110237 |FSA_TARGET { $$ = FSA_TARGET;} 10475184Sek110237 |FSA_ITERS { $$ = FSA_ITERS;} 10485184Sek110237 |FSA_VALUE { $$ = FSA_VALUE;} 10495184Sek110237 |FSA_BLOCKING { $$ = FSA_BLOCKING;} 10505184Sek110237 |FSA_HIGHWATER { $$ = FSA_HIGHWATER;} 10515184Sek110237 |FSA_IOSIZE { $$ = FSA_IOSIZE;}; 10525184Sek110237 10535184Sek110237 attrs_eventgen: 10545184Sek110237 FSA_RATE { $$ = FSA_RATE;}; 10555184Sek110237 10565184Sek110237 attr_value: var_string_list { 10575184Sek110237 if (($$ = alloc_attr()) == NULL) 10585184Sek110237 YYERROR; 10595184Sek110237 $$->attr_param_list = $1; 10605184Sek110237 } | FSV_STRING 10615184Sek110237 { 10625184Sek110237 if (($$ = alloc_attr()) == NULL) 10635184Sek110237 YYERROR; 10645184Sek110237 $$->attr_string = string_alloc($1); 10655184Sek110237 } | FSV_VAL_INT { 10665184Sek110237 if (($$ = alloc_attr()) == NULL) 10675184Sek110237 YYERROR; 10685184Sek110237 $$->attr_integer = integer_alloc($1); 10695184Sek110237 } | FSV_VARIABLE { 10705184Sek110237 if (($$ = alloc_attr()) == NULL) 10715184Sek110237 YYERROR; 10725184Sek110237 $$->attr_integer = var_ref_integer($1); 10735184Sek110237 $$->attr_string = var_ref_string($1); 10745184Sek110237 }; 10755184Sek110237 10765184Sek110237 %% 10775184Sek110237 10785184Sek110237 /* 10795184Sek110237 * The following 'c' routines implement the various commands defined in the 10805184Sek110237 * above yacc parser code. The yacc portion checks the syntax of the commands 10815184Sek110237 * found in a workload file, or typed on interactive command lines, parsing 10825184Sek110237 * the commands' parameters into lists. The lists are then passed in a cmd_t 10835184Sek110237 * struct for each command to its related routine in the following section 10845184Sek110237 * for actual execution. This section also includes a few utility routines 10855184Sek110237 * and the main entry point for the program. 10865184Sek110237 */ 10875184Sek110237 10885184Sek110237 /* 10895184Sek110237 * Entry point for filebench. Processes command line arguements. The -f 10905184Sek110237 * option will read in a workload file (the full name and extension must 10915184Sek110237 * must be given). The -a, -s, -m and -i options are used by worker process 10925184Sek110237 * to receive their name, the base address of shared memory, its path, and 10935184Sek110237 * the process' instance number, respectively. This information is supplied 10945184Sek110237 * by the master process when it execs worker processes under the process 10955184Sek110237 * model of execution. If the worker process arguments are passed then main 10965184Sek110237 * will call the procflow_exec routine which creates worker threadflows and 10975184Sek110237 * flowops and executes the procflow's portion of the workload model until 10985184Sek110237 * completion. If worker process arguments are not passed to the process, 10995184Sek110237 * then it becomes the master process for a filebench run. It initializes 11005184Sek110237 * the various filebench components and either executes the supplied workload 11015184Sek110237 * file, or enters interactive mode. 11025184Sek110237 */ 11035184Sek110237 11045184Sek110237 int 11055184Sek110237 main(int argc, char *argv[]) 11065184Sek110237 { 11075184Sek110237 int opt; 11085184Sek110237 int docmd = FS_FALSE; 11095184Sek110237 int instance; 11105184Sek110237 char procname[128]; 11115184Sek110237 caddr_t shmaddr; 11125184Sek110237 char dir[MAXPATHLEN]; 11135184Sek110237 #ifdef HAVE_SETRLIMIT 11145184Sek110237 struct rlimit rlp; 11155184Sek110237 #endif 11165184Sek110237 #ifdef HAVE_LIBTECLA 11175184Sek110237 char *line; 11185184Sek110237 #else 11195184Sek110237 char line[1024]; 11205184Sek110237 #endif 11215184Sek110237 char shmpathtmp[1024]; 11225184Sek110237 11235184Sek110237 #ifdef HAVE_SETRLIMIT 11245184Sek110237 /* Set resource limits */ 11255184Sek110237 (void) getrlimit(RLIMIT_NOFILE, &rlp); 11265184Sek110237 rlp.rlim_cur = rlp.rlim_max; 11275184Sek110237 setrlimit(RLIMIT_NOFILE, &rlp); 11285184Sek110237 #endif 11295184Sek110237 11305184Sek110237 yydebug = 0; 11315184Sek110237 execname = argv[0]; 11325184Sek110237 *procname = 0; 11335184Sek110237 cwd = getcwd(dir, MAXPATHLEN); 11345184Sek110237 11355184Sek110237 while ((opt = getopt(argc, argv, cmd_options)) != (int)EOF) { 11365184Sek110237 11375184Sek110237 switch (opt) { 11385184Sek110237 case 'h': 11395184Sek110237 usage(2); 11405184Sek110237 break; 11415184Sek110237 11425184Sek110237 case 'p': 11435184Sek110237 noproc = 1; 11445184Sek110237 break; 11455184Sek110237 11465184Sek110237 case 'f': 11475184Sek110237 if (optarg == NULL) 11485184Sek110237 usage(1); 11495184Sek110237 if ((yyin = fopen(optarg, "r")) == NULL) { 11505184Sek110237 (void) fprintf(stderr, 11515184Sek110237 "Cannot open file %s", optarg); 11525184Sek110237 exit(1); 11535184Sek110237 } 11545184Sek110237 dofile = FS_TRUE; 11555184Sek110237 fscriptname = optarg; 11565184Sek110237 11575184Sek110237 break; 11585184Sek110237 11595184Sek110237 case 'a': 11605184Sek110237 if (optarg == NULL) 11615184Sek110237 usage(1); 11625184Sek110237 sscanf(optarg, "%s", &procname[0]); 11635184Sek110237 break; 11645184Sek110237 11655184Sek110237 case 's': 11665184Sek110237 if (optarg == NULL) 11675184Sek110237 usage(1); 11685184Sek110237 #if defined(_LP64) || (__WORDSIZE == 64) 11695184Sek110237 sscanf(optarg, "%llx", &shmaddr); 11705184Sek110237 #else 11715184Sek110237 sscanf(optarg, "%x", &shmaddr); 11725184Sek110237 #endif 11735184Sek110237 break; 11745184Sek110237 11755184Sek110237 case 'm': 11765184Sek110237 if (optarg == NULL) 11775184Sek110237 usage(1); 11785184Sek110237 sscanf(optarg, "%s", shmpathtmp); 11795184Sek110237 shmpath = shmpathtmp; 11805184Sek110237 break; 11815184Sek110237 11825184Sek110237 case 'i': 11835184Sek110237 if (optarg == NULL) 11845184Sek110237 usage(1); 11855184Sek110237 sscanf(optarg, "%d", &instance); 11865184Sek110237 break; 11875184Sek110237 11885184Sek110237 case '?': 11895184Sek110237 default: 11905184Sek110237 usage(1); 11915184Sek110237 break; 11925184Sek110237 } 11935184Sek110237 } 11945184Sek110237 11955184Sek110237 #ifdef USE_PROCESS_MODEL 11965184Sek110237 if (!(*procname)) 11975184Sek110237 #endif 11985184Sek110237 printf("FileBench Version %s\n", FILEBENCH_VERSION); 11995184Sek110237 filebench_init(); 12005184Sek110237 1201*6084Saw148015 /* get process pid for use with message logging */ 1202*6084Saw148015 my_pid = getpid(); 1203*6084Saw148015 12045184Sek110237 #ifdef USE_PROCESS_MODEL 12055184Sek110237 if (*procname) { 1206*6084Saw148015 /* A child FileBench instance */ 12075184Sek110237 if (ipc_attach(shmaddr) < 0) { 12085184Sek110237 filebench_log(LOG_ERROR, "Cannot attach shm for %s", 12095184Sek110237 procname); 12105184Sek110237 exit(1); 12115184Sek110237 } 12125184Sek110237 1213*6084Saw148015 if (procflow_exec(procname, instance) < 0) 12145184Sek110237 exit(1); 1215*6084Saw148015 1216*6084Saw148015 exit(0); 12175184Sek110237 } 12185184Sek110237 #endif 12195184Sek110237 1220*6084Saw148015 /* master (or only) process */ 12215184Sek110237 ipc_init(); 12225184Sek110237 12235184Sek110237 if (fscriptname) 12245184Sek110237 (void) strcpy(filebench_shm->fscriptname, fscriptname); 12255184Sek110237 12265184Sek110237 flowop_init(); 12275184Sek110237 stats_init(); 12285184Sek110237 eventgen_init(); 12295184Sek110237 12305184Sek110237 signal(SIGINT, parser_abort); 12315184Sek110237 12325184Sek110237 if (dofile) 12335184Sek110237 yyparse(); 12345184Sek110237 else { 12355184Sek110237 #ifdef HAVE_LIBTECLA 12365184Sek110237 if ((gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL) { 12375184Sek110237 filebench_log(LOG_ERROR, 12385184Sek110237 "Failed to create GetLine object"); 12395184Sek110237 filebench_shutdown(1); 12405184Sek110237 } 12415184Sek110237 12425184Sek110237 if (gl_customize_completion(gl, NULL, command_complete)) { 12435184Sek110237 filebench_log(LOG_ERROR, 12445184Sek110237 "Failed to register auto-completion function"); 12455184Sek110237 filebench_shutdown(1); 12465184Sek110237 } 12475184Sek110237 12485184Sek110237 while (line = gl_get_line(gl, FILEBENCH_PROMPT, NULL, -1)) { 12495184Sek110237 arg_parse(line); 12505184Sek110237 yyparse(); 12515184Sek110237 } 12525184Sek110237 12535184Sek110237 del_GetLine(gl); 12545184Sek110237 #else 12555184Sek110237 while (!feof(stdin)) { 12565184Sek110237 printf(FILEBENCH_PROMPT); 12575184Sek110237 fflush(stdout); 12585184Sek110237 if (fgets(line, sizeof (line), stdin) == NULL) { 12595184Sek110237 if (errno == EINTR) 12605184Sek110237 continue; 12615184Sek110237 else 12625184Sek110237 break; 12635184Sek110237 } 12645184Sek110237 arg_parse(line); 12655184Sek110237 yyparse(); 12665184Sek110237 } 12675184Sek110237 printf("\n"); 12685184Sek110237 #endif /* HAVE_LIBTECLA */ 12695184Sek110237 } 12705184Sek110237 12715184Sek110237 parser_filebench_shutdown((cmd_t *)0); 12725184Sek110237 12735184Sek110237 return (0); 12745184Sek110237 } 12755184Sek110237 12765184Sek110237 /* 12775184Sek110237 * arg_parse() puts the parser into command parsing mode. Create a tmpfile 12785184Sek110237 * and instruct the parser to read instructions from this location by setting 12795184Sek110237 * yyin to the value returned by tmpfile. Write the command into the file. 12805184Sek110237 * Then seek back to to the start of the file so that the parser can read 12815184Sek110237 * the instructions. 12825184Sek110237 */ 12835184Sek110237 static void 12845184Sek110237 arg_parse(const char *command) 12855184Sek110237 { 12865184Sek110237 if ((yyin = tmpfile()) == NULL) 12875184Sek110237 filebench_log(LOG_FATAL, 12885184Sek110237 "Cannot create tmpfile: %s", strerror(errno)); 12895184Sek110237 12905184Sek110237 if (fwrite(command, strlen(command), 1, yyin) != 1) 12915184Sek110237 filebench_log(LOG_FATAL, 12925184Sek110237 "Cannot write tmpfile: %s", strerror(errno)); 12935184Sek110237 12945184Sek110237 if (fseek(yyin, 0, SEEK_SET) != 0) 12955184Sek110237 filebench_log(LOG_FATAL, 12965184Sek110237 "Cannot seek tmpfile: %s", strerror(errno)); 12975184Sek110237 } 12985184Sek110237 12995184Sek110237 /* 13005184Sek110237 * Converts a list of var_strings or ordinary strings to a single ordinary 13015184Sek110237 * string. It returns a pointer to the string (in malloc'd memory) if found, 13025184Sek110237 * or NULL otherwise. 13035184Sek110237 */ 13045184Sek110237 char * 13055184Sek110237 parser_list2string(list_t *list) 13065184Sek110237 { 13075184Sek110237 list_t *l; 13085184Sek110237 char *string; 13095184Sek110237 char *tmp; 13105184Sek110237 vinteger_t *integer; 13115184Sek110237 13125184Sek110237 if ((string = malloc(MAXPATHLEN)) == NULL) { 13135184Sek110237 filebench_log(LOG_ERROR, "Failed to allocate memory"); 13145184Sek110237 return (NULL); 13155184Sek110237 } 13165184Sek110237 13175184Sek110237 *string = 0; 13185184Sek110237 13195184Sek110237 13205184Sek110237 /* Format args */ 13215184Sek110237 for (l = list; l != NULL; 13225184Sek110237 l = l->list_next) { 13235184Sek110237 filebench_log(LOG_DEBUG_SCRIPT, 13245184Sek110237 "converting string '%s'", *l->list_string); 13255184Sek110237 13265184Sek110237 if ((tmp = var_to_string(*l->list_string)) != NULL) { 13275184Sek110237 (void) strcat(string, tmp); 13285184Sek110237 free(tmp); 13295184Sek110237 } else { 13305184Sek110237 (void) strcat(string, *l->list_string); 13315184Sek110237 } 13325184Sek110237 } 13335184Sek110237 return (string); 13345184Sek110237 } 13355184Sek110237 13365184Sek110237 /* 13375184Sek110237 * If the list just contains a single string starting with '$', then find 13385184Sek110237 * or create the named var and return the var's var_string component. 13395184Sek110237 * Otherwise, convert the list to a string, and allocate a var_string 13405184Sek110237 * containing a copy of that string. On failure either returns NULL 13415184Sek110237 * or shuts down the run. 13425184Sek110237 */ 13435184Sek110237 var_string_t 13445184Sek110237 parser_list2varstring(list_t *list) 13455184Sek110237 { 13465184Sek110237 /* Special case - variable name */ 13475184Sek110237 if ((list->list_next == NULL) && (*(*list->list_string) == '$')) 13485184Sek110237 return (var_ref_string(*list->list_string)); 13495184Sek110237 13505184Sek110237 return (string_alloc(parser_list2string(list))); 13515184Sek110237 } 13525184Sek110237 13535184Sek110237 /* 13545184Sek110237 * Looks for the var named in list_string of the first element of the 13555184Sek110237 * supplied list. If found, returns the var_integer portion of the var. 13565184Sek110237 * If the var is not found, cannot be allocated, the supplied list is 13575184Sek110237 * NULL, or the list_string filed is empty, returns NULL. 13585184Sek110237 */ 13595184Sek110237 var_integer_t 13605184Sek110237 parser_list2integer(list_t *list) 13615184Sek110237 { 13625184Sek110237 var_integer_t v; 13635184Sek110237 13645184Sek110237 if (list && (*(list->list_string) != NULL)) { 13655184Sek110237 v = var_ref_integer(*(list->list_string)); 13665184Sek110237 return (v); 13675184Sek110237 } 13685184Sek110237 13695184Sek110237 return (NULL); 13705184Sek110237 } 13715184Sek110237 13725184Sek110237 /* 13735184Sek110237 * Sets the event generator rate from the attribute supplied with the 13745184Sek110237 * command. If the attribute doesn't exist the routine does nothing. 13755184Sek110237 */ 13765184Sek110237 static void 13775184Sek110237 parser_eventgen(cmd_t *cmd) 13785184Sek110237 { 13795184Sek110237 attr_t *attr; 13805184Sek110237 vinteger_t rate; 13815184Sek110237 13825184Sek110237 /* Get the rate from attribute */ 13835184Sek110237 if (attr = get_attr_integer(cmd, FSA_RATE)) { 13845184Sek110237 if (attr->attr_integer) { 13855184Sek110237 filebench_log(LOG_VERBOSE, 13865184Sek110237 "Eventgen: %lld per second", 13875184Sek110237 *attr->attr_integer); 13885184Sek110237 eventgen_setrate(*attr->attr_integer); 13895184Sek110237 } 13905184Sek110237 } 13915184Sek110237 13925184Sek110237 } 13935184Sek110237 13945184Sek110237 /* 13955184Sek110237 * Assigns the designated integer variable successive values from the 13965184Sek110237 * supplied comma seperated integer list. After each successive integer 13975184Sek110237 * assignment, it executes the bracket enclosed list of commands. For 13985184Sek110237 * example, repeated runs of a workload with increasing io sizes can 13995184Sek110237 * be done using the following command line: 14005184Sek110237 * foreach $iosize in 2k, 4k, 8k {run 60} 14015184Sek110237 */ 14025184Sek110237 static void 14035184Sek110237 parser_foreach_integer(cmd_t *cmd) 14045184Sek110237 { 14055184Sek110237 list_t *list = cmd->cmd_param_list; 14065184Sek110237 cmd_t *inner_cmd; 14075184Sek110237 14085184Sek110237 for (; list != NULL; list = list->list_next) { 14095184Sek110237 var_assign_integer(cmd->cmd_tgt1, *list->list_integer); 14105184Sek110237 filebench_log(LOG_VERBOSE, "Iterating %s=%lld", 14115184Sek110237 cmd->cmd_tgt1, 14125184Sek110237 *list->list_integer); 14135184Sek110237 for (inner_cmd = cmd->cmd_list; inner_cmd != NULL; 14145184Sek110237 inner_cmd = inner_cmd->cmd_next) { 14155184Sek110237 inner_cmd->cmd(inner_cmd); 14165184Sek110237 } 14175184Sek110237 } 14185184Sek110237 } 14195184Sek110237 14205184Sek110237 /* 14215184Sek110237 * Similar to parser_foreach_integer(), except takes a list of strings after 14225184Sek110237 * the "in" token. For example, to run twice using a different directory, 14235184Sek110237 * perhaps using a different filesystem, the following command line 14245184Sek110237 * could be used: 14255184Sek110237 * foreach $dir in "/ufs_top/fbt", "/zfs_top/fbt" {run 60) 14265184Sek110237 */ 14275184Sek110237 static void 14285184Sek110237 parser_foreach_string(cmd_t *cmd) 14295184Sek110237 { 14305184Sek110237 list_t *list = cmd->cmd_param_list; 14315184Sek110237 cmd_t *inner_cmd; 14325184Sek110237 14335184Sek110237 for (; list != NULL; list = list->list_next) { 14345184Sek110237 var_assign_string(cmd->cmd_tgt1, *list->list_string); 14355184Sek110237 filebench_log(LOG_VERBOSE, "Iterating %s=%s", 14365184Sek110237 cmd->cmd_tgt1, 14375184Sek110237 *list->list_string); 14385184Sek110237 for (inner_cmd = cmd->cmd_list; inner_cmd != NULL; 14395184Sek110237 inner_cmd = inner_cmd->cmd_next) { 14405184Sek110237 inner_cmd->cmd(inner_cmd); 14415184Sek110237 } 14425184Sek110237 } 14435184Sek110237 } 14445184Sek110237 14455184Sek110237 /* 14465673Saw148015 * Lists the fileset name, path name and average size for all defined 14475673Saw148015 * filesets. 14485184Sek110237 */ 14495184Sek110237 static void 14505184Sek110237 parser_list(cmd_t *cmd) 14515184Sek110237 { 14525673Saw148015 (void) fileset_iter(fileset_print); 14535184Sek110237 } 14545184Sek110237 14555184Sek110237 /* 14565184Sek110237 * Calls procflow_define() to allocate "instances" number of procflow(s) 14575184Sek110237 * (processes) with the supplied name. The default number of instances is 14585184Sek110237 * one. An optional priority level attribute can be supplied and is stored in 14595184Sek110237 * pf_nice. Finally the routine loops through the list of inner commands, if 14605184Sek110237 * any, which are defines for threadflows, and passes them one at a time to 14615184Sek110237 * parser_thread_define() to allocate threadflow entities for the process(es). 14625184Sek110237 */ 14635184Sek110237 static void 14645184Sek110237 parser_proc_define(cmd_t *cmd) 14655184Sek110237 { 14665184Sek110237 procflow_t *procflow, template; 14675184Sek110237 char *name; 14685184Sek110237 attr_t *attr; 14695184Sek110237 var_integer_t instances = integer_alloc(1); 14705184Sek110237 cmd_t *inner_cmd; 14715184Sek110237 14725184Sek110237 /* Get the name of the process */ 14735184Sek110237 if (attr = get_attr(cmd, FSA_NAME)) { 14745184Sek110237 name = *attr->attr_string; 14755184Sek110237 } else { 14765184Sek110237 filebench_log(LOG_ERROR, 14775184Sek110237 "define proc: proc specifies no name"); 14785184Sek110237 filebench_shutdown(1); 14795184Sek110237 } 14805184Sek110237 14815184Sek110237 /* Get the memory size from attribute */ 14825184Sek110237 if (attr = get_attr_integer(cmd, FSA_INSTANCES)) { 14835184Sek110237 filebench_log(LOG_DEBUG_IMPL, 14845184Sek110237 "Setting instances = %lld", 14855184Sek110237 *attr->attr_integer); 14865184Sek110237 instances = attr->attr_integer; 14875184Sek110237 } 14885184Sek110237 14895184Sek110237 if ((procflow = procflow_define(name, NULL, instances)) == NULL) { 14905184Sek110237 filebench_log(LOG_ERROR, 14915184Sek110237 "Failed to instantiate %d %s process(es)\n", 14925184Sek110237 instances, name); 14935184Sek110237 filebench_shutdown(1); 14945184Sek110237 } 14955184Sek110237 14965184Sek110237 /* Get the pri from attribute */ 14975184Sek110237 if (attr = get_attr_integer(cmd, FSA_NICE)) { 14985184Sek110237 filebench_log(LOG_DEBUG_IMPL, "Setting pri = %lld", 14995184Sek110237 *attr->attr_integer); 15005184Sek110237 procflow->pf_nice = attr->attr_integer; 15015184Sek110237 } else 15025184Sek110237 procflow->pf_nice = integer_alloc(0); 15035184Sek110237 15045184Sek110237 15055184Sek110237 /* Create the list of threads for this process */ 15065184Sek110237 for (inner_cmd = cmd->cmd_list; inner_cmd != NULL; 15075184Sek110237 inner_cmd = inner_cmd->cmd_next) { 15085184Sek110237 parser_thread_define(inner_cmd, procflow, *instances); 15095184Sek110237 } 15105184Sek110237 } 15115184Sek110237 15125184Sek110237 /* 15135184Sek110237 * Calls threadflow_define() to allocate "instances" number of threadflow(s) 15145184Sek110237 * (threads) with the supplied name. The default number of instances is 15155184Sek110237 * one. Two other optional attributes may be supplied, one to set the memory 15165184Sek110237 * size, stored in tf_memsize, and to select the use of Interprocess Shared 15175184Sek110237 * Memory, which sets the THREADFLOW_USEISM flag in tf_attrs. Finally 15185184Sek110237 * the routine loops through the list of inner commands, if any, which are 15195184Sek110237 * defines for flowops, and passes them one at a time to 15205184Sek110237 * parser_flowop_define() to allocate flowop entities for the threadflows. 15215184Sek110237 */ 15225184Sek110237 static void 15235184Sek110237 parser_thread_define(cmd_t *cmd, procflow_t *procflow, int procinstances) 15245184Sek110237 { 15255184Sek110237 threadflow_t *threadflow, template; 15265184Sek110237 attr_t *attr; 15275184Sek110237 var_integer_t instances = integer_alloc(1); 15285184Sek110237 cmd_t *inner_cmd; 15295184Sek110237 char *name; 15305184Sek110237 15315184Sek110237 memset(&template, 0, sizeof (threadflow_t)); 15325184Sek110237 15335184Sek110237 /* Get the name of the thread */ 15345184Sek110237 if (attr = get_attr(cmd, FSA_NAME)) { 15355184Sek110237 name = *attr->attr_string; 15365184Sek110237 } else { 15375184Sek110237 filebench_log(LOG_ERROR, 15385184Sek110237 "define thread: thread in process %s specifies no name", 15395184Sek110237 procflow->pf_name); 15405184Sek110237 filebench_shutdown(1); 15415184Sek110237 } 15425184Sek110237 15435184Sek110237 /* Get the number of instances from attribute */ 15445184Sek110237 if (attr = get_attr_integer(cmd, FSA_INSTANCES)) { 15455184Sek110237 filebench_log(LOG_DEBUG_IMPL, 15465184Sek110237 "define thread: Setting instances = %lld", 15475184Sek110237 *attr->attr_integer); 15485184Sek110237 instances = attr->attr_integer; 15495184Sek110237 } 15505184Sek110237 15515184Sek110237 /* Get the memory size from attribute */ 15525184Sek110237 if (attr = get_attr_integer(cmd, FSA_MEMSIZE)) { 15535184Sek110237 filebench_log(LOG_DEBUG_IMPL, 15545184Sek110237 "define thread: Setting memsize = %lld", 15555184Sek110237 *attr->attr_integer); 15565184Sek110237 template.tf_memsize = attr->attr_integer; 15575184Sek110237 } else 15585184Sek110237 template.tf_memsize = integer_alloc(0); 15595184Sek110237 15605184Sek110237 if ((threadflow = threadflow_define(procflow, name, 15615184Sek110237 &template, instances)) == NULL) { 15625184Sek110237 filebench_log(LOG_ERROR, 15635184Sek110237 "define thread: Failed to instantiate thread\n"); 15645184Sek110237 filebench_shutdown(1); 15655184Sek110237 } 15665184Sek110237 15675184Sek110237 /* Use ISM Memory? */ 15685184Sek110237 if (attr = get_attr(cmd, FSA_USEISM)) { 15695184Sek110237 threadflow->tf_attrs |= THREADFLOW_USEISM; 15705184Sek110237 } 15715184Sek110237 15725184Sek110237 /* Create the list of flowops */ 15735184Sek110237 for (inner_cmd = cmd->cmd_list; inner_cmd != NULL; 15745184Sek110237 inner_cmd = inner_cmd->cmd_next) { 15755184Sek110237 parser_flowop_define(inner_cmd, threadflow); 15765184Sek110237 } 15775184Sek110237 } 15785184Sek110237 15795184Sek110237 /* 15805184Sek110237 * Calls flowop_define() to allocate a flowop with the supplied name. 15815184Sek110237 * The allocated flowop inherits attributes from a base flowop of the 15825184Sek110237 * same type. If the new flowop has a file or fileset attribute specified, 15835184Sek110237 * it must specify a defined fileobj or fileset or an error will be logged. 15845184Sek110237 * The new flowop may also have the following attributes set by 15855184Sek110237 * the program: 15865184Sek110237 * - file size (fo_iosize) 15875184Sek110237 * - working set size (fo_wss) 15885184Sek110237 * - do random io (fo_random) 15895184Sek110237 * - do synchronous io (fo_dsync) 15905184Sek110237 * - perform each operation multiple times before advancing (fo_iter) 15915184Sek110237 * - target name (fo_targetname) 15925184Sek110237 * - An integer value (fo_value) 15935184Sek110237 * - a file descriptor (fo_fd) 15945184Sek110237 * - specify to rotate file descriptors (fo_rotatefd) 15955184Sek110237 * - a source fd (fo_srcfdnumber) 15965184Sek110237 * - specify a blocking operation (fo_blocking) 15975184Sek110237 * - specify a highwater mark (fo_highwater) 15985184Sek110237 * 15995184Sek110237 * After all the supplied attributes are stored in their respective locations 16005184Sek110237 * in the flowop object, the flowop's init function is called. No errors are 16015184Sek110237 * returned, but the filebench run will be terminated if the flowtype is not 16025184Sek110237 * specified, a name for the new flowop is not supplied, the flowop_define 16035184Sek110237 * call fails, or a file or fileset name is supplied but the corresponding 16045184Sek110237 * fileobj or fileset cannot be located. 16055184Sek110237 */ 16065184Sek110237 static void 16075184Sek110237 parser_flowop_define(cmd_t *cmd, threadflow_t *thread) 16085184Sek110237 { 16095184Sek110237 flowop_t *flowop, *flowop_type; 16105184Sek110237 char *type = (char *)cmd->cmd_name; 16115184Sek110237 char *name; 16125184Sek110237 attr_t *attr; 16135184Sek110237 16145184Sek110237 /* Get the inherited flowop */ 16155184Sek110237 flowop_type = flowop_find(type); 16165184Sek110237 if (flowop_type == NULL) { 16175184Sek110237 filebench_log(LOG_ERROR, 16185184Sek110237 "define flowop: flowop type %s not found", 16195184Sek110237 type); 16205184Sek110237 filebench_shutdown(1); 16215184Sek110237 } 16225184Sek110237 16235184Sek110237 /* Get the name of the flowop */ 16245184Sek110237 if (attr = get_attr(cmd, FSA_NAME)) { 16255184Sek110237 name = *attr->attr_string; 16265184Sek110237 } else { 16275184Sek110237 filebench_log(LOG_ERROR, 16285184Sek110237 "define flowop: flowop %s specifies no name", 16295184Sek110237 flowop_type->fo_name); 16305184Sek110237 filebench_shutdown(1); 16315184Sek110237 } 16325184Sek110237 16335184Sek110237 if ((flowop = flowop_define(thread, name, 16345184Sek110237 flowop_type, FLOW_MASTER, 0)) == NULL) { 16355184Sek110237 filebench_log(LOG_ERROR, 16365184Sek110237 "define flowop: Failed to instantiate flowop %s\n", 16375184Sek110237 cmd->cmd_name); 16385184Sek110237 filebench_shutdown(1); 16395184Sek110237 } 16405184Sek110237 16415184Sek110237 /* Get the filename from attribute */ 16425184Sek110237 if (attr = get_attr(cmd, FSA_FILE)) { 16435184Sek110237 flowop->fo_fileset = fileset_find(*attr->attr_string); 16445184Sek110237 16455673Saw148015 if ((flowop->fo_fileset == NULL)) { 16465184Sek110237 filebench_log(LOG_ERROR, 16475184Sek110237 "define flowop: file %s not found", 16485184Sek110237 *attr->attr_string); 16495184Sek110237 filebench_shutdown(1); 16505184Sek110237 } 16515184Sek110237 } 16525184Sek110237 16535184Sek110237 /* Get the iosize of the op */ 16545184Sek110237 if (attr = get_attr_integer(cmd, FSA_IOSIZE)) 16555184Sek110237 flowop->fo_iosize = attr->attr_integer; 16565184Sek110237 else 16575184Sek110237 flowop->fo_iosize = integer_alloc(0); 16585184Sek110237 16595184Sek110237 /* Get the working set size of the op */ 16605184Sek110237 if (attr = get_attr_integer(cmd, FSA_WSS)) 16615184Sek110237 flowop->fo_wss = attr->attr_integer; 16625184Sek110237 else 16635184Sek110237 flowop->fo_wss = integer_alloc(0); 16645184Sek110237 16655184Sek110237 /* Random I/O? */ 16665184Sek110237 if (attr = get_attr_bool(cmd, FSA_RANDOM)) 16675184Sek110237 flowop->fo_random = attr->attr_integer; 16685184Sek110237 else 16695184Sek110237 flowop->fo_random = integer_alloc(0); 16705184Sek110237 16715184Sek110237 /* Sync I/O? */ 16725184Sek110237 if (attr = get_attr_bool(cmd, FSA_DSYNC)) 16735184Sek110237 flowop->fo_dsync = attr->attr_integer; 16745184Sek110237 else 16755184Sek110237 flowop->fo_dsync = integer_alloc(0); 16765184Sek110237 16775184Sek110237 /* Iterations */ 16785184Sek110237 if (attr = get_attr_integer(cmd, FSA_ITERS)) 16795184Sek110237 flowop->fo_iters = attr->attr_integer; 16805184Sek110237 else 16815184Sek110237 flowop->fo_iters = integer_alloc(1); 16825184Sek110237 16835184Sek110237 16845184Sek110237 /* Target, for wakeup etc */ 16855184Sek110237 if (attr = get_attr(cmd, FSA_TARGET)) 16865184Sek110237 (void) strcpy(flowop->fo_targetname, *attr->attr_string); 16875184Sek110237 16885184Sek110237 /* Value */ 16895184Sek110237 if (attr = get_attr_integer(cmd, FSA_VALUE)) 16905184Sek110237 flowop->fo_value = attr->attr_integer; 16915184Sek110237 else 16925184Sek110237 flowop->fo_value = integer_alloc(0); 16935184Sek110237 16945184Sek110237 /* FD */ 16955184Sek110237 if (attr = get_attr_integer(cmd, FSA_FD)) 16965184Sek110237 flowop->fo_fdnumber = *attr->attr_integer; 16975184Sek110237 16985184Sek110237 /* Rotatefd? */ 16995184Sek110237 if (attr = get_attr_bool(cmd, FSA_ROTATEFD)) 17005184Sek110237 flowop->fo_rotatefd = attr->attr_integer; 17015184Sek110237 else 17025184Sek110237 flowop->fo_rotatefd = integer_alloc(0); 17035184Sek110237 17045184Sek110237 /* SRC FD, for copies etc... */ 17055184Sek110237 if (attr = get_attr_integer(cmd, FSA_SRCFD)) 17065184Sek110237 flowop->fo_srcfdnumber = *attr->attr_integer; 17075184Sek110237 17085184Sek110237 /* Blocking operation? */ 17095184Sek110237 if (attr = get_attr_bool(cmd, FSA_BLOCKING)) 17105184Sek110237 flowop->fo_blocking = attr->attr_integer; 17115184Sek110237 else 17125184Sek110237 flowop->fo_blocking = integer_alloc(0); 17135184Sek110237 17145184Sek110237 /* Blocking operation? */ 17155184Sek110237 if (attr = get_attr_bool(cmd, FSA_DIRECTIO)) 17165184Sek110237 flowop->fo_directio = attr->attr_integer; 17175184Sek110237 else 17185184Sek110237 flowop->fo_directio = integer_alloc(0); 17195184Sek110237 17205184Sek110237 /* Highwater mark */ 17215184Sek110237 if (attr = get_attr_integer(cmd, FSA_HIGHWATER)) 17225184Sek110237 flowop->fo_highwater = attr->attr_integer; 17235184Sek110237 else 17245184Sek110237 flowop->fo_highwater = integer_alloc(1); 17255184Sek110237 } 17265184Sek110237 17275184Sek110237 /* 17285184Sek110237 * Calls fileset_define() to allocate a fileset with the supplied name and 17295184Sek110237 * initializes the fileset's pathname attribute, and optionally the fs_cached, 17305673Saw148015 * fs_reuse, fs_prealloc and fs_size attributes. 17315673Saw148015 * 17325184Sek110237 */ 17335673Saw148015 static fileset_t * 17345673Saw148015 parser_fileset_define_common(cmd_t *cmd) 17355184Sek110237 { 17365184Sek110237 fileset_t *fileset; 17375184Sek110237 char *name; 17385184Sek110237 attr_t *attr; 17395184Sek110237 var_string_t pathname; 17405184Sek110237 17415184Sek110237 /* Get the name of the file */ 17425184Sek110237 if (attr = get_attr(cmd, FSA_NAME)) { 17435184Sek110237 name = *attr->attr_string; 17445184Sek110237 } else { 17455184Sek110237 filebench_log(LOG_ERROR, 17465673Saw148015 "define fileset: file or fileset specifies no name"); 17475673Saw148015 return (NULL); 17485184Sek110237 } 17495184Sek110237 17505184Sek110237 if ((fileset = fileset_define(name)) == NULL) { 17515184Sek110237 filebench_log(LOG_ERROR, 17525184Sek110237 "define file: failed to instantiate file %s\n", 17535673Saw148015 name); 17545673Saw148015 return (NULL); 17555184Sek110237 } 17565184Sek110237 17575184Sek110237 /* Get the pathname from attribute */ 17585184Sek110237 if ((attr = get_attr(cmd, FSA_PATH)) == NULL) { 17595184Sek110237 filebench_log(LOG_ERROR, "define file: no pathname specified"); 17605673Saw148015 return (NULL); 17615184Sek110237 } 17625184Sek110237 17635184Sek110237 /* Expand variables in pathname */ 17645673Saw148015 if ((pathname = parser_list2varstring(attr->attr_param_list)) 17655673Saw148015 == NULL) { 17665184Sek110237 filebench_log(LOG_ERROR, "Cannot interpret path"); 17675673Saw148015 return (NULL); 17685184Sek110237 } 17695184Sek110237 17705184Sek110237 fileset->fs_path = pathname; 17715184Sek110237 17725673Saw148015 /* Should we prealloc in parallel? */ 17735673Saw148015 if (attr = get_attr_bool(cmd, FSA_PARALLOC)) { 17745673Saw148015 fileset->fs_paralloc = attr->attr_integer; 17755673Saw148015 } else 17765673Saw148015 fileset->fs_paralloc = integer_alloc(0); 17775673Saw148015 17785673Saw148015 /* Should we reuse the existing file? */ 17795673Saw148015 if (attr = get_attr_bool(cmd, FSA_REUSE)) { 17805673Saw148015 fileset->fs_reuse = attr->attr_integer; 17815673Saw148015 } else 17825673Saw148015 fileset->fs_reuse = integer_alloc(0); 17835673Saw148015 17845184Sek110237 /* Should we leave in cache? */ 17855184Sek110237 if (attr = get_attr_bool(cmd, FSA_CACHED)) { 17865184Sek110237 fileset->fs_cached = attr->attr_integer; 17875184Sek110237 } else 17885184Sek110237 fileset->fs_cached = integer_alloc(0); 17895184Sek110237 17905673Saw148015 /* Get the mean or absolute size of the file */ 17915673Saw148015 if (attr = get_attr_integer(cmd, FSA_SIZE)) { 17925673Saw148015 fileset->fs_size = attr->attr_integer; 17935184Sek110237 } else 17945673Saw148015 fileset->fs_size = integer_alloc(0); 17955673Saw148015 17965673Saw148015 return (fileset); 17975673Saw148015 } 17985673Saw148015 17995673Saw148015 /* 18005673Saw148015 * Calls parser_fileset_define_common() to allocate a fileset with 18015673Saw148015 * one entry and optionally the fs_prealloc. Sets the fs_preallocpercent, 18025673Saw148015 * fs_entries, fs_dirwidth, fs_dirgamma, and fs_sizegamma attributes 18035673Saw148015 * to appropriate values for emulating the old "fileobj" entity 18045673Saw148015 */ 18055673Saw148015 static void 18065673Saw148015 parser_file_define(cmd_t *cmd) 18075673Saw148015 { 18085673Saw148015 fileset_t *fileset; 18095673Saw148015 attr_t *attr; 18105673Saw148015 18115673Saw148015 if ((fileset = parser_fileset_define_common(cmd)) == NULL) { 18125673Saw148015 filebench_log(LOG_ERROR, 18135673Saw148015 "define file: failed to instantiate file"); 18145673Saw148015 filebench_shutdown(1); 18155673Saw148015 return; 18165673Saw148015 } 18175673Saw148015 18185673Saw148015 /* fileset is emulating a single file */ 18195673Saw148015 fileset->fs_attrs = FILESET_IS_FILE; 18205673Saw148015 18215673Saw148015 /* Set the size of the fileset to 1 */ 18225673Saw148015 fileset->fs_entries = integer_alloc(1); 18235673Saw148015 18245673Saw148015 /* Set the mean dir width to more than 1 */ 18255673Saw148015 fileset->fs_dirwidth = integer_alloc(10); 18265673Saw148015 18275673Saw148015 /* Set the dir and size gammas to 0 */ 18285673Saw148015 fileset->fs_dirgamma = integer_alloc(0); 18295673Saw148015 fileset->fs_sizegamma = integer_alloc(0); 18305673Saw148015 18315673Saw148015 /* if a raw device, all done */ 18325673Saw148015 if (fileset_checkraw(fileset)) { 18335673Saw148015 filebench_log(LOG_VERBOSE, "File %s/%s is RAW device", 18345673Saw148015 *fileset->fs_path, fileset->fs_name); 18355673Saw148015 return; 18365673Saw148015 } 18375673Saw148015 18385673Saw148015 /* Does file need to be preallocated? */ 18395673Saw148015 if (attr = get_attr_bool(cmd, FSA_PREALLOC)) { 18405673Saw148015 /* yes */ 18415673Saw148015 fileset->fs_prealloc = attr->attr_integer; 18425673Saw148015 fileset->fs_preallocpercent = integer_alloc(100); 18435673Saw148015 } else { 18445673Saw148015 /* no */ 18455673Saw148015 fileset->fs_prealloc = integer_alloc(0); 18465673Saw148015 fileset->fs_preallocpercent = integer_alloc(0); 18475673Saw148015 } 18485673Saw148015 } 18495673Saw148015 18505673Saw148015 /* 18515673Saw148015 * Calls parser_fileset_define_common() to allocate a fileset with the 18525673Saw148015 * supplied name and initializes the fileset's fs_preallocpercent, 18535673Saw148015 * fs_prealloc, fs_entries, fs_dirwidth, fs_dirgamma, and fs_sizegamma 18545673Saw148015 * attributes. 18555673Saw148015 */ 18565673Saw148015 static void 18575673Saw148015 parser_fileset_define(cmd_t *cmd) 18585673Saw148015 { 18595673Saw148015 fileset_t *fileset; 18605673Saw148015 attr_t *attr; 18615673Saw148015 18625673Saw148015 if ((fileset = parser_fileset_define_common(cmd)) == NULL) { 18635673Saw148015 filebench_log(LOG_ERROR, 18645673Saw148015 "define fileset: failed to instantiate fileset"); 18655673Saw148015 filebench_shutdown(1); 18665673Saw148015 return; 18675673Saw148015 } 18685673Saw148015 18695673Saw148015 /* if a raw device, Error */ 18705673Saw148015 if (fileset_checkraw(fileset)) { 18715673Saw148015 filebench_log(LOG_ERROR, 18725673Saw148015 "Fileset %s/%s: Cannot create a fileset on a RAW device", 18735673Saw148015 *fileset->fs_path, fileset->fs_name); 18745673Saw148015 filebench_shutdown(0); 18755673Saw148015 return; 18765673Saw148015 } 18775673Saw148015 18785673Saw148015 /* How much should we preallocate? */ 18795184Sek110237 if ((attr = get_attr_integer(cmd, FSA_PREALLOC)) && 18805184Sek110237 attr->attr_integer) { 18815184Sek110237 fileset->fs_preallocpercent = attr->attr_integer; 18825184Sek110237 } else if (attr && !attr->attr_integer) { 18835184Sek110237 fileset->fs_preallocpercent = integer_alloc(100); 18845184Sek110237 } else { 18855184Sek110237 fileset->fs_preallocpercent = integer_alloc(0); 18865184Sek110237 } 18875184Sek110237 18885184Sek110237 /* Should we preallocate? */ 18895184Sek110237 if (attr = get_attr_bool(cmd, FSA_PREALLOC)) { 18905184Sek110237 fileset->fs_prealloc = attr->attr_integer; 18915184Sek110237 } else 18925184Sek110237 fileset->fs_prealloc = integer_alloc(0); 18935184Sek110237 18945673Saw148015 /* Get the number of files in the fileset */ 18955184Sek110237 if (attr = get_attr_integer(cmd, FSA_ENTRIES)) { 18965184Sek110237 fileset->fs_entries = attr->attr_integer; 18975184Sek110237 } else { 18985184Sek110237 filebench_log(LOG_ERROR, "Fileset has zero entries"); 18995184Sek110237 fileset->fs_entries = integer_alloc(0); 19005184Sek110237 } 19015184Sek110237 19025184Sek110237 /* Get the mean dir width of the fileset */ 19035184Sek110237 if (attr = get_attr_integer(cmd, FSA_DIRWIDTH)) { 19045184Sek110237 fileset->fs_dirwidth = attr->attr_integer; 19055184Sek110237 } else { 19065184Sek110237 filebench_log(LOG_ERROR, "Fileset has zero directory width"); 19075184Sek110237 fileset->fs_dirwidth = integer_alloc(0); 19085184Sek110237 } 19095184Sek110237 19105184Sek110237 /* Get the gamma value for dir width distributions */ 19115184Sek110237 if (attr = get_attr_integer(cmd, FSA_DIRGAMMA)) { 19125184Sek110237 fileset->fs_dirgamma = attr->attr_integer; 19135184Sek110237 } else 19145184Sek110237 fileset->fs_dirgamma = integer_alloc(1500); 19155184Sek110237 19165184Sek110237 /* Get the gamma value for dir width distributions */ 19175184Sek110237 if (attr = get_attr_integer(cmd, FSA_FILESIZEGAMMA)) { 19185184Sek110237 fileset->fs_sizegamma = attr->attr_integer; 19195184Sek110237 } else 19205184Sek110237 fileset->fs_sizegamma = integer_alloc(1500); 19215184Sek110237 } 19225184Sek110237 19235184Sek110237 /* 19245184Sek110237 * Creates and starts all defined procflow processes. The call to 19255184Sek110237 * procflow_init() results in creation of the requested number of 19265184Sek110237 * process instances for each previously defined procflow. The 19275184Sek110237 * child processes exec() a new instance of filebench, passing it 19285184Sek110237 * the instance number and address of the shared memory region. 19295184Sek110237 * The child processes will then create their threads and flowops. 19305184Sek110237 * The routine then unlocks the run_lock to allow all the processes' 19315184Sek110237 * threads to start and waits for all of them to begin execution. 19325184Sek110237 * Finally, it records the start time and resets the event generation 19335184Sek110237 * system. 19345184Sek110237 */ 19355184Sek110237 static void 19365184Sek110237 parser_proc_create(cmd_t *cmd) 19375184Sek110237 { 1938*6084Saw148015 filebench_shm->shm_1st_err = 0; 19395184Sek110237 if (procflow_init() != 0) { 19405184Sek110237 filebench_log(LOG_ERROR, "Failed to create processes\n"); 19415184Sek110237 filebench_shutdown(1); 19425184Sek110237 } 19435184Sek110237 19445184Sek110237 /* Release the read lock, allowing threads to start */ 19455184Sek110237 (void) pthread_rwlock_unlock(&filebench_shm->run_lock); 19465184Sek110237 19475184Sek110237 /* Wait for all threads to start */ 19485184Sek110237 if (procflow_allstarted() != 0) { 19495184Sek110237 filebench_log(LOG_ERROR, "Could not start run"); 19505184Sek110237 return; 19515184Sek110237 } 19525184Sek110237 19535184Sek110237 19545184Sek110237 if (filebench_shm->shm_required && 19555184Sek110237 (ipc_ismcreate(filebench_shm->shm_required) < 0)) { 19565184Sek110237 filebench_log(LOG_ERROR, "Could not allocate shared memory"); 19575184Sek110237 return; 19585184Sek110237 } 19595184Sek110237 19605184Sek110237 filebench_shm->starttime = gethrtime(); 19615184Sek110237 eventgen_reset(); 19625184Sek110237 } 19635184Sek110237 19645184Sek110237 /* 19655673Saw148015 * Calls fileset_createset() to populate all files and filesets and 19665673Saw148015 * create all associated, initially existant, files and subdirectories. 19675184Sek110237 * If errors are encountered, calls filebench_shutdown() 19685184Sek110237 * to exit filebench. 19695184Sek110237 */ 19705184Sek110237 static void 19715184Sek110237 parser_fileset_create(cmd_t *cmd) 19725184Sek110237 { 19735673Saw148015 if (!filecreate_done) { 19745673Saw148015 filecreate_done = 1; 19755673Saw148015 if (fileset_createset(NULL) != 0) { 19765673Saw148015 filebench_log(LOG_ERROR, "Failed to create filesets"); 19775673Saw148015 filebench_shutdown(1); 19785673Saw148015 } 19795673Saw148015 } else { 19805673Saw148015 filebench_log(LOG_INFO, 19815673Saw148015 "Attempting to create fileset more than once, ignoring"); 19825184Sek110237 } 19835673Saw148015 19845184Sek110237 } 19855184Sek110237 19865184Sek110237 /* 19875184Sek110237 * Shuts down all processes and their associated threads. When finished 19885184Sek110237 * it deletes interprocess shared memory and resets the event generator. 19895184Sek110237 * It does not exit the filebench program though. 19905184Sek110237 */ 19915184Sek110237 static void 19925184Sek110237 parser_proc_shutdown(cmd_t *cmd) 19935184Sek110237 { 19945184Sek110237 filebench_log(LOG_INFO, "Shutting down processes"); 19955673Saw148015 filecreate_done = 0; 19965184Sek110237 procflow_shutdown(); 19975184Sek110237 if (filebench_shm->shm_required) 19985184Sek110237 ipc_ismdelete(); 19995184Sek110237 eventgen_reset(); 20005184Sek110237 } 20015184Sek110237 20025184Sek110237 /* 20035184Sek110237 * Ends filebench run after first destoring any interprocess 20045184Sek110237 * shared memory. The call to filebench_shutdown() 20055184Sek110237 * also causes filebench to exit. 20065184Sek110237 */ 20075184Sek110237 static void 20085184Sek110237 parser_filebench_shutdown(cmd_t *cmd) 20095184Sek110237 { 20105184Sek110237 ipc_cleanup(); 20115184Sek110237 filebench_shutdown(1); 20125184Sek110237 } 20135184Sek110237 20145184Sek110237 /* 2015*6084Saw148015 * This is Used for timing runs.Pauses the master thread in one second 2016*6084Saw148015 * intervals until the supplied ptime runs out or the f_abort flag 2017*6084Saw148015 * is raised. If given a time of zero or less, or the mode is stop on 2018*6084Saw148015 * lack of resources, it will pause until f_abort is raised. 20195184Sek110237 */ 20205184Sek110237 static void 2021*6084Saw148015 parser_pause(int ptime) 20225184Sek110237 { 2023*6084Saw148015 int timeslept = 0; 2024*6084Saw148015 2025*6084Saw148015 if ((filebench_shm->shm_rmode == FILEBENCH_MODE_TIMEOUT) && 2026*6084Saw148015 (ptime > 0)) { 2027*6084Saw148015 while (timeslept < ptime) { 2028*6084Saw148015 (void) sleep(1); 2029*6084Saw148015 timeslept++; 2030*6084Saw148015 if (filebench_shm->f_abort) 2031*6084Saw148015 break; 2032*6084Saw148015 } 2033*6084Saw148015 } else { 2034*6084Saw148015 /* initial runtime of 0 means run till abort */ 2035*6084Saw148015 /* CONSTCOND */ 2036*6084Saw148015 while (1) { 2037*6084Saw148015 (void) sleep(1); 2038*6084Saw148015 timeslept++; 2039*6084Saw148015 if (filebench_shm->f_abort) 2040*6084Saw148015 break; 2041*6084Saw148015 } 20425184Sek110237 } 2043*6084Saw148015 2044*6084Saw148015 filebench_log(LOG_INFO, "Run took %lld seconds...", timeslept); 20455184Sek110237 } 20465184Sek110237 20475184Sek110237 /* 20485184Sek110237 * Do a file bench run. Calls routines to create file sets, files, and 20495184Sek110237 * processes. It resets the statistics counters, then sleeps for the runtime 20505184Sek110237 * passed as an argument to it on the command line in 1 second increments. 20515184Sek110237 * When it is finished sleeping, it collects a snapshot of the statistics 20525184Sek110237 * and ends the run. 20535184Sek110237 */ 20545184Sek110237 static void 20555184Sek110237 parser_run(cmd_t *cmd) 20565184Sek110237 { 20575184Sek110237 int runtime; 20585184Sek110237 20595184Sek110237 runtime = cmd->cmd_qty; 2060*6084Saw148015 20615184Sek110237 parser_fileset_create(cmd); 20625184Sek110237 parser_proc_create(cmd); 20635184Sek110237 20645184Sek110237 /* check for startup errors */ 20655184Sek110237 if (filebench_shm->f_abort) 20665184Sek110237 return; 20675184Sek110237 20685184Sek110237 filebench_log(LOG_INFO, "Running..."); 20695184Sek110237 stats_clear(); 2070*6084Saw148015 2071*6084Saw148015 parser_pause(runtime); 2072*6084Saw148015 20735184Sek110237 parser_statssnap(cmd); 20745184Sek110237 parser_proc_shutdown(cmd); 20755184Sek110237 } 20765184Sek110237 20775184Sek110237 /* 20785184Sek110237 * Similar to parser_run, but gets the sleep time from a variable 20795184Sek110237 * whose name is supplied as an argument to the command. 20805184Sek110237 */ 20815184Sek110237 static void 20825184Sek110237 parser_run_variable(cmd_t *cmd) 20835184Sek110237 { 20845184Sek110237 vinteger_t *integer = var_ref_integer(cmd->cmd_tgt1); 20855184Sek110237 int runtime; 20865184Sek110237 20875184Sek110237 if (integer == NULL) { 20885184Sek110237 filebench_log(LOG_ERROR, "Unknown variable %s", 20895184Sek110237 cmd->cmd_tgt1); 20905184Sek110237 return; 20915184Sek110237 } 20925184Sek110237 20935184Sek110237 runtime = *integer; 20945184Sek110237 20955184Sek110237 /* check for startup errors */ 20965184Sek110237 if (filebench_shm->f_abort) 20975184Sek110237 return; 20985184Sek110237 20995184Sek110237 filebench_log(LOG_INFO, "Running..."); 21005184Sek110237 stats_clear(); 2101*6084Saw148015 2102*6084Saw148015 parser_pause(runtime); 2103*6084Saw148015 21045184Sek110237 parser_statssnap(cmd); 2105*6084Saw148015 parser_proc_shutdown(cmd); 21065184Sek110237 } 21075184Sek110237 21085184Sek110237 char *usagestr = NULL; 21095184Sek110237 21105184Sek110237 /* 21115184Sek110237 * Prints usage string if defined, else just a message requesting load of a 21125184Sek110237 * personality. 21135184Sek110237 */ 21145184Sek110237 static void 21155184Sek110237 parser_help(cmd_t *cmd) 21165184Sek110237 { 21175184Sek110237 int runtime; 21185184Sek110237 21195184Sek110237 if (usagestr) { 21205184Sek110237 filebench_log(LOG_INFO, "%s", usagestr); 21215184Sek110237 } else { 21225184Sek110237 filebench_log(LOG_INFO, 21235184Sek110237 "load <personality> (ls " 21245184Sek110237 "/usr/benchmarks/filebench/workloads for list)"); 21255184Sek110237 } 21265184Sek110237 } 21275184Sek110237 21285184Sek110237 char *varstr = NULL; 21295184Sek110237 21305184Sek110237 /* 21315184Sek110237 * Prints the string of all var definitions, if there is one. 21325184Sek110237 */ 21335184Sek110237 static void 21345184Sek110237 parser_printvars(cmd_t *cmd) 21355184Sek110237 { 21365184Sek110237 int runtime; 21375184Sek110237 char *str, *c; 21385184Sek110237 21395184Sek110237 if (varstr) { 21405184Sek110237 str = strdup(varstr); 21415184Sek110237 for (c = str; *c != '\0'; c++) { 21425184Sek110237 if ((char)*c == '$') 21435184Sek110237 *c = ' '; 21445184Sek110237 } 21455184Sek110237 filebench_log(LOG_INFO, "%s", str); 21465184Sek110237 free(str); 21475184Sek110237 } 21485184Sek110237 } 21495184Sek110237 21505184Sek110237 /* 21515184Sek110237 * Used by the SET command to add a var and default value string to the 21525184Sek110237 * varstr string. It allocates a new, larger varstr string, copies the 21535184Sek110237 * old contents of varstr into it, then adds the new var string on the end. 21545184Sek110237 */ 21555184Sek110237 static void 21565184Sek110237 parser_vars(cmd_t *cmd) 21575184Sek110237 { 21585184Sek110237 char *string = cmd->cmd_tgt1; 21595184Sek110237 char *newvars; 21605184Sek110237 21615184Sek110237 if (string == NULL) 21625184Sek110237 return; 21635184Sek110237 21645184Sek110237 if (dofile) 21655184Sek110237 return; 21665184Sek110237 21675184Sek110237 if (varstr == NULL) { 21685184Sek110237 newvars = malloc(strlen(string) + 2); 21695184Sek110237 *newvars = 0; 21705184Sek110237 } else { 21715184Sek110237 newvars = malloc(strlen(varstr) + strlen(string) + 2); 21725184Sek110237 (void) strcpy(newvars, varstr); 21735184Sek110237 } 21745184Sek110237 (void) strcat(newvars, string); 21755184Sek110237 (void) strcat(newvars, " "); 21765184Sek110237 21775184Sek110237 if (varstr) 21785184Sek110237 free(varstr); 21795184Sek110237 21805184Sek110237 varstr = newvars; 21815184Sek110237 } 21825184Sek110237 21835184Sek110237 /* 2184*6084Saw148015 * Sleeps for cmd->cmd_qty seconds, one second at a time. 2185*6084Saw148015 */ 2186*6084Saw148015 static void 2187*6084Saw148015 parser_sleep(cmd_t *cmd) 2188*6084Saw148015 { 2189*6084Saw148015 int sleeptime; 2190*6084Saw148015 2191*6084Saw148015 /* check for startup errors */ 2192*6084Saw148015 if (filebench_shm->f_abort) 2193*6084Saw148015 return; 2194*6084Saw148015 2195*6084Saw148015 sleeptime = cmd->cmd_qty; 2196*6084Saw148015 filebench_log(LOG_INFO, "Running..."); 2197*6084Saw148015 2198*6084Saw148015 parser_pause(sleeptime); 2199*6084Saw148015 } 2200*6084Saw148015 2201*6084Saw148015 /* 22025184Sek110237 * Same as parser_sleep, except the sleep time is obtained from a variable 22035184Sek110237 * whose name is passed to it as an argument on the command line. 22045184Sek110237 */ 22055184Sek110237 static void 22065184Sek110237 parser_sleep_variable(cmd_t *cmd) 22075184Sek110237 { 22085184Sek110237 vinteger_t *integer = var_ref_integer(cmd->cmd_tgt1); 22095184Sek110237 int sleeptime; 22105184Sek110237 22115184Sek110237 if (integer == NULL) { 22125184Sek110237 filebench_log(LOG_ERROR, "Unknown variable %s", 22135184Sek110237 cmd->cmd_tgt1); 22145184Sek110237 return; 22155184Sek110237 } 22165184Sek110237 22175184Sek110237 sleeptime = *integer; 22185184Sek110237 22195184Sek110237 /* check for startup errors */ 22205184Sek110237 if (filebench_shm->f_abort) 22215184Sek110237 return; 22225184Sek110237 22235184Sek110237 filebench_log(LOG_INFO, "Running..."); 2224*6084Saw148015 2225*6084Saw148015 parser_pause(sleeptime); 22265184Sek110237 } 22275184Sek110237 22285184Sek110237 /* 22295184Sek110237 * Parser log prints the values of a list of variables to the log file. 22305184Sek110237 * The list of variables is placed on the command line, separated 22315184Sek110237 * by comas and the entire list is enclosed in quotes. 22325184Sek110237 * For example, if $dir contains "/export/home/tmp" and $filesize = 1048576, 22335184Sek110237 * then typing: log "$dir, $filesize" prints: log /export/home/tmp, 1048576 22345184Sek110237 */ 22355184Sek110237 static void 22365184Sek110237 parser_log(cmd_t *cmd) 22375184Sek110237 { 22385184Sek110237 char *string; 22395184Sek110237 22405184Sek110237 if (cmd->cmd_param_list == NULL) 22415184Sek110237 return; 22425184Sek110237 22435184Sek110237 string = parser_list2string(cmd->cmd_param_list); 22445184Sek110237 22455184Sek110237 if (string == NULL) 22465184Sek110237 return; 22475184Sek110237 22485184Sek110237 filebench_log(LOG_VERBOSE, "log %s", string); 22495184Sek110237 filebench_log(LOG_LOG, "%s", string); 22505184Sek110237 } 22515184Sek110237 22525184Sek110237 /* 22535184Sek110237 * Implements the stats directory command. changes the directory for 22545184Sek110237 * dumping statistics to supplied directory path. For example: 22555184Sek110237 * stats directory /tmp 22565184Sek110237 * changes the stats directory to "/tmp". 22575184Sek110237 */ 22585184Sek110237 static void 22595184Sek110237 parser_directory(cmd_t *cmd) 22605184Sek110237 { 22615184Sek110237 char newdir[MAXPATHLEN]; 22625184Sek110237 char *dir; 22635184Sek110237 22645184Sek110237 if ((dir = parser_list2string(cmd->cmd_param_list)) == NULL) { 22655184Sek110237 filebench_log(LOG_ERROR, "Cannot interpret directory"); 22665184Sek110237 return; 22675184Sek110237 } 22685184Sek110237 22695184Sek110237 *newdir = 0; 22705184Sek110237 /* Change dir relative to cwd if path not fully qualified */ 22715184Sek110237 if (*dir != '/') { 22725184Sek110237 (void) strcat(newdir, cwd); 22735184Sek110237 (void) strcat(newdir, "/"); 22745184Sek110237 } 22755184Sek110237 (void) strcat(newdir, dir); 22765184Sek110237 (void) mkdir(newdir, 0755); 22775184Sek110237 filebench_log(LOG_VERBOSE, "Change dir to %s", newdir); 22785184Sek110237 chdir(newdir); 22795184Sek110237 free(dir); 22805184Sek110237 } 22815184Sek110237 22825184Sek110237 #define PIPE_PARENT 1 22835184Sek110237 #define PIPE_CHILD 0 22845184Sek110237 22855184Sek110237 /* 22865184Sek110237 * Runs the quoted unix command as a background process. Intended for 22875184Sek110237 * running statistics gathering utilities such as mpstat while the filebench 22885184Sek110237 * workload is running. Also records the pid's of the background processes 22895184Sek110237 * so that parser_statssnap() can terminate them when the run completes. 22905184Sek110237 */ 22915184Sek110237 static void 22925184Sek110237 parser_statscmd(cmd_t *cmd) 22935184Sek110237 { 22945184Sek110237 char *string; 22955184Sek110237 pid_t pid; 22965184Sek110237 pidlist_t *pidlistent; 22975184Sek110237 int pipe_fd[2]; 22985184Sek110237 int newstdout; 22995184Sek110237 23005184Sek110237 if (cmd->cmd_param_list == NULL) 23015184Sek110237 return; 23025184Sek110237 23035184Sek110237 string = parser_list2string(cmd->cmd_param_list); 23045184Sek110237 23055184Sek110237 if (string == NULL) 23065184Sek110237 return; 23075184Sek110237 23085184Sek110237 if ((pipe(pipe_fd)) < 0) { 23095184Sek110237 filebench_log(LOG_ERROR, "statscmd pipe failed"); 23105184Sek110237 return; 23115184Sek110237 } 23125184Sek110237 23135184Sek110237 #ifdef HAVE_FORK1 23145184Sek110237 if ((pid = fork1()) < 0) { 23155184Sek110237 filebench_log(LOG_ERROR, "statscmd fork failed"); 23165184Sek110237 return; 23175184Sek110237 } 23185184Sek110237 #elif HAVE_FORK 23195184Sek110237 if ((pid = fork()) < 0) { 23205184Sek110237 filebench_log(LOG_ERROR, "statscmd fork failed"); 23215184Sek110237 return; 23225184Sek110237 } 23235184Sek110237 #else 23245184Sek110237 Crash! - Need code to deal with no fork1! 23255184Sek110237 #endif /* HAVE_FORK1 */ 23265184Sek110237 23275184Sek110237 if (pid == 0) { 23285184Sek110237 23295184Sek110237 setsid(); 23305184Sek110237 23315184Sek110237 filebench_log(LOG_VERBOSE, 23325184Sek110237 "Backgrounding %s", string); 23335184Sek110237 /* 23345184Sek110237 * Child 23355184Sek110237 * - close stdout 23365184Sek110237 * - dup to create new stdout 23375184Sek110237 * - close pipe fds 23385184Sek110237 */ 23395184Sek110237 (void) close(1); 23405184Sek110237 23415184Sek110237 if ((newstdout = dup(pipe_fd[PIPE_CHILD])) < 0) { 23425184Sek110237 filebench_log(LOG_ERROR, 23435184Sek110237 "statscmd dup failed: %s", 23445184Sek110237 strerror(errno)); 23455184Sek110237 } 23465184Sek110237 23475184Sek110237 (void) close(pipe_fd[PIPE_PARENT]); 23485184Sek110237 (void) close(pipe_fd[PIPE_CHILD]); 23495184Sek110237 23505184Sek110237 if (system(string) < 0) { 23515184Sek110237 filebench_log(LOG_ERROR, 23525184Sek110237 "statscmd exec failed: %s", 23535184Sek110237 strerror(errno)); 23545184Sek110237 } 23555184Sek110237 /* Failed! */ 23565184Sek110237 exit(1); 23575184Sek110237 23585184Sek110237 } else { 23595184Sek110237 23605184Sek110237 /* Record pid in pidlist for subsequent reaping by stats snap */ 23615184Sek110237 if ((pidlistent = (pidlist_t *)malloc(sizeof (pidlist_t))) 23625184Sek110237 == NULL) { 23635184Sek110237 filebench_log(LOG_ERROR, "pidlistent malloc failed"); 23645184Sek110237 return; 23655184Sek110237 } 23665184Sek110237 23675184Sek110237 pidlistent->pl_pid = pid; 23685184Sek110237 pidlistent->pl_fd = pipe_fd[PIPE_PARENT]; 23695184Sek110237 (void) close(pipe_fd[PIPE_CHILD]); 23705184Sek110237 23715184Sek110237 /* Add fileobj to global list */ 23725184Sek110237 if (pidlist == NULL) { 23735184Sek110237 pidlist = pidlistent; 23745184Sek110237 pidlistent->pl_next = NULL; 23755184Sek110237 } else { 23765184Sek110237 pidlistent->pl_next = pidlist; 23775184Sek110237 pidlist = pidlistent; 23785184Sek110237 } 23795184Sek110237 } 23805184Sek110237 } 23815184Sek110237 23825184Sek110237 /* 23835184Sek110237 * Launches a shell to run the unix command supplied in the argument. 23845184Sek110237 * The command should be enclosed in quotes, as in: 23855184Sek110237 * system "rm xyz" 23865184Sek110237 * which would run the "rm" utility to delete the file "xyz". 23875184Sek110237 */ 23885184Sek110237 static void 23895184Sek110237 parser_system(cmd_t *cmd) 23905184Sek110237 { 23915184Sek110237 char *string; 23925184Sek110237 23935184Sek110237 if (cmd->cmd_param_list == NULL) 23945184Sek110237 return; 23955184Sek110237 23965184Sek110237 string = parser_list2string(cmd->cmd_param_list); 23975184Sek110237 23985184Sek110237 if (string == NULL) 23995184Sek110237 return; 24005184Sek110237 24015184Sek110237 filebench_log(LOG_VERBOSE, 24025184Sek110237 "Running '%s'", string); 24035184Sek110237 24045184Sek110237 if (system(string) < 0) { 24055184Sek110237 filebench_log(LOG_ERROR, 24065184Sek110237 "system exec failed: %s", 24075184Sek110237 strerror(errno)); 24085184Sek110237 } 24095184Sek110237 free(string); 24105184Sek110237 } 24115184Sek110237 24125184Sek110237 /* 24135184Sek110237 * Echos string supplied with command to the log. 24145184Sek110237 */ 24155184Sek110237 static void 24165184Sek110237 parser_echo(cmd_t *cmd) 24175184Sek110237 { 24185184Sek110237 char *string; 24195184Sek110237 24205184Sek110237 if (cmd->cmd_param_list == NULL) 24215184Sek110237 return; 24225184Sek110237 24235184Sek110237 string = parser_list2string(cmd->cmd_param_list); 24245184Sek110237 24255184Sek110237 if (string == NULL) 24265184Sek110237 return; 24275184Sek110237 24285184Sek110237 filebench_log(LOG_INFO, "%s", string); 24295184Sek110237 } 24305184Sek110237 24315184Sek110237 24325184Sek110237 /* 24335184Sek110237 * Adds the string supplied as the argument to the usage command 24345184Sek110237 * to the end of the string printed by the help command. 24355184Sek110237 */ 24365184Sek110237 static void 24375184Sek110237 parser_usage(cmd_t *cmd) 24385184Sek110237 { 24395184Sek110237 char *string; 24405184Sek110237 char *newusage; 24415184Sek110237 24425184Sek110237 if (cmd->cmd_param_list == NULL) 24435184Sek110237 return; 24445184Sek110237 24455184Sek110237 string = parser_list2string(cmd->cmd_param_list); 24465184Sek110237 24475184Sek110237 if (string == NULL) 24485184Sek110237 return; 24495184Sek110237 24505184Sek110237 if (dofile) 24515184Sek110237 return; 24525184Sek110237 24535184Sek110237 if (usagestr == NULL) { 24545184Sek110237 newusage = malloc(strlen(string) + 2); 24555184Sek110237 *newusage = 0; 24565184Sek110237 } else { 24575184Sek110237 newusage = malloc(strlen(usagestr) + strlen(string) + 2); 24585184Sek110237 (void) strcpy(newusage, usagestr); 24595184Sek110237 } 24605184Sek110237 (void) strcat(newusage, "\n"); 24615184Sek110237 (void) strcat(newusage, string); 24625184Sek110237 24635184Sek110237 if (usagestr) 24645184Sek110237 free(usagestr); 24655184Sek110237 24665184Sek110237 usagestr = newusage; 24675184Sek110237 24685184Sek110237 filebench_log(LOG_INFO, "%s", string); 24695184Sek110237 } 24705184Sek110237 24715184Sek110237 /* 24725184Sek110237 * Updates the global dump filename with the filename supplied 24735184Sek110237 * as the command's argument. Then dumps the statistics of each 24745184Sek110237 * worker flowop into the dump file, followed by a summary of 24755184Sek110237 * overall totals. 24765184Sek110237 */ 24775184Sek110237 static void 24785184Sek110237 parser_statsdump(cmd_t *cmd) 24795184Sek110237 { 24805184Sek110237 char *string; 24815184Sek110237 24825184Sek110237 if (cmd->cmd_param_list == NULL) 24835184Sek110237 return; 24845184Sek110237 24855184Sek110237 string = parser_list2string(cmd->cmd_param_list); 24865184Sek110237 24875184Sek110237 if (string == NULL) 24885184Sek110237 return; 24895184Sek110237 24905184Sek110237 filebench_log(LOG_VERBOSE, 24915184Sek110237 "Stats dump to file '%s'", string); 24925184Sek110237 24935184Sek110237 stats_dump(string); 24945184Sek110237 24955184Sek110237 free(string); 24965184Sek110237 } 24975184Sek110237 24985184Sek110237 /* 24995184Sek110237 * Same as parser_statsdump, but in xml format. 25005184Sek110237 */ 25015184Sek110237 static void 25025184Sek110237 parser_statsxmldump(cmd_t *cmd) 25035184Sek110237 { 25045184Sek110237 char *string; 25055184Sek110237 25065184Sek110237 if (cmd->cmd_param_list == NULL) 25075184Sek110237 return; 25085184Sek110237 25095184Sek110237 string = parser_list2string(cmd->cmd_param_list); 25105184Sek110237 25115184Sek110237 if (string == NULL) 25125184Sek110237 return; 25135184Sek110237 25145184Sek110237 filebench_log(LOG_VERBOSE, 25155184Sek110237 "Stats dump to file '%s'", string); 25165184Sek110237 25175184Sek110237 stats_xmldump(string); 25185184Sek110237 25195184Sek110237 free(string); 25205184Sek110237 } 25215184Sek110237 25225184Sek110237 /* 25235184Sek110237 * Kills off background statistics collection processes, then takes a snapshot 25245184Sek110237 * of the filebench run's collected statistics using stats_snap() from 25255184Sek110237 * stats.c. 25265184Sek110237 */ 25275184Sek110237 static void 25285184Sek110237 parser_statssnap(cmd_t *cmd) 25295184Sek110237 { 25305184Sek110237 pidlist_t *pidlistent; 25315184Sek110237 int stat; 25325184Sek110237 pid_t pid; 25335184Sek110237 25345184Sek110237 for (pidlistent = pidlist; pidlistent != NULL; 25355184Sek110237 pidlistent = pidlistent->pl_next) { 25365184Sek110237 filebench_log(LOG_VERBOSE, "Killing session %d for pid %d", 25375184Sek110237 getsid(pidlistent->pl_pid), 25385184Sek110237 pidlistent->pl_pid); 25395184Sek110237 if (pidlistent->pl_fd) 25405184Sek110237 (void) close(pidlistent->pl_fd); 25415184Sek110237 #ifdef HAVE_SIGSEND 25425184Sek110237 sigsend(P_SID, getsid(pidlistent->pl_pid), SIGTERM); 25435184Sek110237 #else 25445184Sek110237 (void) kill(-1, SIGTERM); 25455184Sek110237 #endif 25465184Sek110237 25475184Sek110237 /* Close pipe */ 25485184Sek110237 if (pidlistent->pl_fd) 25495184Sek110237 (void) close(pidlistent->pl_fd); 25505184Sek110237 25515184Sek110237 /* Wait for cmd and all its children */ 25525184Sek110237 while ((pid = waitpid(pidlistent->pl_pid * -1, &stat, 0)) > 0) 25535184Sek110237 filebench_log(LOG_DEBUG_IMPL, 25545184Sek110237 "Waited for pid %lld", pid); 25555184Sek110237 } 25565184Sek110237 25575184Sek110237 for (pidlistent = pidlist; pidlistent != NULL; 25585184Sek110237 pidlistent = pidlistent->pl_next) { 25595184Sek110237 free(pidlistent); 25605184Sek110237 } 25615184Sek110237 25625184Sek110237 pidlist = NULL; 25635184Sek110237 stats_snap(); 25645184Sek110237 } 25655184Sek110237 25665184Sek110237 /* 25675184Sek110237 * Shutdown filebench. 25685184Sek110237 */ 25695184Sek110237 static void 25705184Sek110237 parser_abort(int arg) 25715184Sek110237 { 25725184Sek110237 (void) sigignore(SIGINT); 25735184Sek110237 filebench_log(LOG_INFO, "Aborting..."); 25745184Sek110237 filebench_shutdown(1); 25755184Sek110237 } 25765184Sek110237 25775184Sek110237 /* 25785184Sek110237 * alloc_cmd() allocates the required resources for a cmd_t. On failure, a 25795184Sek110237 * filebench_log is issued and NULL is returned. 25805184Sek110237 */ 25815184Sek110237 static cmd_t * 25825184Sek110237 alloc_cmd(void) 25835184Sek110237 { 25845184Sek110237 cmd_t *cmd; 25855184Sek110237 25865184Sek110237 if ((cmd = malloc(sizeof (cmd_t))) == NULL) { 25875184Sek110237 filebench_log(LOG_ERROR, "Alloc cmd failed"); 25885184Sek110237 return (NULL); 25895184Sek110237 } 25905184Sek110237 25915184Sek110237 (void) memset(cmd, 0, sizeof (cmd_t)); 25925184Sek110237 25935184Sek110237 return (cmd); 25945184Sek110237 } 25955184Sek110237 25965184Sek110237 /* 25975184Sek110237 * Frees the resources of a cmd_t and then the cmd_t "cmd" itself. 25985184Sek110237 */ 25995184Sek110237 static void 26005184Sek110237 free_cmd(cmd_t *cmd) 26015184Sek110237 { 26025184Sek110237 free((void *)cmd->cmd_tgt1); 26035184Sek110237 free((void *)cmd->cmd_tgt2); 26045184Sek110237 free(cmd); 26055184Sek110237 } 26065184Sek110237 26075184Sek110237 /* 26085184Sek110237 * Allocates an attr_t structure and zeros it. Returns NULL on failure, or 26095184Sek110237 * a pointer to the attr_t. 26105184Sek110237 */ 26115184Sek110237 static attr_t * 26125184Sek110237 alloc_attr() 26135184Sek110237 { 26145184Sek110237 attr_t *attr; 26155184Sek110237 26165184Sek110237 if ((attr = malloc(sizeof (attr_t))) == NULL) { 26175184Sek110237 return (NULL); 26185184Sek110237 } 26195184Sek110237 26205184Sek110237 (void) memset(attr, 0, sizeof (attr_t)); 26215184Sek110237 return (attr); 26225184Sek110237 } 26235184Sek110237 26245184Sek110237 /* 26255184Sek110237 * Searches the attribute list for the command for the named attribute type. 26265184Sek110237 * The attribute list is created by the parser from the list of attributes 26275184Sek110237 * supplied with certain commands, such as the define and flowop commands. 26285184Sek110237 * Returns a pointer to the attribute structure if the named attribute is 26295184Sek110237 * found, otherwise returns NULL. If the attribute includes a parameter list, 26305184Sek110237 * the list is converted to a string and stored in the attr_string field of 26315184Sek110237 * the returned attr_t struct. 26325184Sek110237 */ 26335184Sek110237 static attr_t * 26345184Sek110237 get_attr(cmd_t *cmd, int64_t name) 26355184Sek110237 { 26365184Sek110237 attr_t *attr; 26375184Sek110237 attr_t *rtn = NULL; 26385184Sek110237 char *string; 26395184Sek110237 26405184Sek110237 for (attr = cmd->cmd_attr_list; attr != NULL; 26415184Sek110237 attr = attr->attr_next) { 26425184Sek110237 filebench_log(LOG_DEBUG_IMPL, 26435184Sek110237 "attr %d = %d %llx?", 26445184Sek110237 attr->attr_name, 26455184Sek110237 name, 26465184Sek110237 attr->attr_integer); 26475184Sek110237 26485184Sek110237 if (attr->attr_name == name) 26495184Sek110237 rtn = attr; 26505184Sek110237 } 26515184Sek110237 26525184Sek110237 if (rtn == NULL) 26535184Sek110237 return (NULL); 26545184Sek110237 26555184Sek110237 if (rtn->attr_param_list) { 26565184Sek110237 filebench_log(LOG_DEBUG_SCRIPT, "attr is param list"); 26575184Sek110237 string = parser_list2string(rtn->attr_param_list); 26585184Sek110237 if (string != NULL) { 26595184Sek110237 rtn->attr_string = string_alloc(string); 26605184Sek110237 filebench_log(LOG_DEBUG_SCRIPT, 26615184Sek110237 "attr string %s", string); 26625184Sek110237 } 26635184Sek110237 } 26645184Sek110237 26655184Sek110237 return (rtn); 26665184Sek110237 } 26675184Sek110237 26685184Sek110237 /* 26695184Sek110237 * Similar to get_attr, but converts the parameter string supplied with the 26705184Sek110237 * named attribute to an integer and stores the integer in the attr_integer 26715184Sek110237 * portion of the returned attr_t struct. 26725184Sek110237 */ 26735184Sek110237 static attr_t * 26745184Sek110237 get_attr_integer(cmd_t *cmd, int64_t name) 26755184Sek110237 { 26765184Sek110237 attr_t *attr; 26775184Sek110237 attr_t *rtn = NULL; 26785184Sek110237 26795184Sek110237 for (attr = cmd->cmd_attr_list; attr != NULL; 26805184Sek110237 attr = attr->attr_next) { 26815184Sek110237 if (attr->attr_name == name) 26825184Sek110237 rtn = attr; 26835184Sek110237 } 26845184Sek110237 26855184Sek110237 if (rtn == NULL) 26865184Sek110237 return (NULL); 26875184Sek110237 26885184Sek110237 if (rtn->attr_param_list) { 26895184Sek110237 rtn->attr_integer = parser_list2integer(rtn->attr_param_list); 26905184Sek110237 } 26915184Sek110237 26925184Sek110237 return (rtn); 26935184Sek110237 } 26945184Sek110237 26955184Sek110237 /* 26965184Sek110237 * Similar to get_attr, but converts the parameter string supplied with the 26975184Sek110237 * named attribute to an integer and stores the integer in the attr_integer 26985184Sek110237 * portion of the returned attr_t struct. If no parameter string is supplied 26995184Sek110237 * then it defaults to TRUE (1). 27005184Sek110237 */ 27015184Sek110237 static attr_t * 27025184Sek110237 get_attr_bool(cmd_t *cmd, int64_t name) 27035184Sek110237 { 27045184Sek110237 attr_t *attr; 27055184Sek110237 attr_t *rtn = NULL; 27065184Sek110237 27075184Sek110237 for (attr = cmd->cmd_attr_list; attr != NULL; 27085184Sek110237 attr = attr->attr_next) { 27095184Sek110237 if (attr->attr_name == name) 27105184Sek110237 rtn = attr; 27115184Sek110237 } 27125184Sek110237 27135184Sek110237 if (rtn == NULL) 27145184Sek110237 return (NULL); 27155184Sek110237 27165184Sek110237 if (rtn->attr_param_list) { 27175184Sek110237 rtn->attr_integer = parser_list2integer(rtn->attr_param_list); 27185184Sek110237 } else if (rtn->attr_integer == 0) { 27195184Sek110237 rtn->attr_integer = integer_alloc(1); 27205184Sek110237 } 27215184Sek110237 27225184Sek110237 return (rtn); 27235184Sek110237 } 27245184Sek110237 27255184Sek110237 /* 27265184Sek110237 * Allocates memory for a list_t structure, initializes it to zero, and 27275184Sek110237 * returns a pointer to it. On failure, returns NULL. 27285184Sek110237 */ 27295184Sek110237 static list_t * 27305184Sek110237 alloc_list() 27315184Sek110237 { 27325184Sek110237 list_t *list; 27335184Sek110237 27345184Sek110237 if ((list = malloc(sizeof (list_t))) == NULL) { 27355184Sek110237 return (NULL); 27365184Sek110237 } 27375184Sek110237 27385184Sek110237 (void) memset(list, 0, sizeof (list_t)); 27395184Sek110237 return (list); 27405184Sek110237 } 27415184Sek110237 27425184Sek110237 27435184Sek110237 #define USAGE1 \ 27445184Sek110237 "Usage:\n" \ 27455184Sek110237 "%s: interpret f script and generate file workload\n" \ 27465184Sek110237 "Options:\n" \ 27475184Sek110237 " [-h] Display verbose help\n" \ 27485184Sek110237 " [-p] Disable opening /proc to set uacct to enable truss\n" 27495184Sek110237 27505184Sek110237 #define PARSER_CMDS \ 27515184Sek110237 "create [files|filesets|processes]\n" \ 27525184Sek110237 "stats [clear|snap]\n" \ 27535184Sek110237 "stats command \"shell command $var1,$var2...\"\n" \ 27545184Sek110237 "stats directory <directory>\n" \ 27555184Sek110237 "sleep <sleep-value>\n" \ 27565184Sek110237 "quit\n\n" \ 27575184Sek110237 "Variables:\n" \ 27585184Sek110237 "set $var = value\n" \ 27595184Sek110237 " $var - regular variables\n" \ 27605184Sek110237 " ${var} - internal special variables\n" \ 27615184Sek110237 " $(var) - environment variables\n\n" 27625184Sek110237 27635184Sek110237 #define PARSER_EXAMPLE \ 27645184Sek110237 "Example:\n\n" \ 27655184Sek110237 "#!/usr/bin/filebench -f\n" \ 27665184Sek110237 "\n" \ 27675184Sek110237 "define file name=bigfile,path=bigfile,size=1g,prealloc,reuse\n" \ 27685184Sek110237 "define process name=randomizer\n" \ 27695184Sek110237 "{\n" \ 27705184Sek110237 " thread random-thread procname=randomizer\n" \ 27715184Sek110237 " {\n" \ 27725184Sek110237 " flowop read name=random-read,filename=bigfile,iosize=16k,random\n" \ 27735184Sek110237 " }\n" \ 27745184Sek110237 "}\n" \ 27755184Sek110237 "create files\n" \ 27765184Sek110237 "create processes\n" \ 27775184Sek110237 "stats clear\n" \ 27785184Sek110237 "sleep 30\n" \ 27795184Sek110237 "stats snap\n" 27805184Sek110237 27815184Sek110237 /* 27825184Sek110237 * usage() display brief or verbose help for the filebench(1) command. 27835184Sek110237 */ 27845184Sek110237 static void 27855184Sek110237 usage(int help) 27865184Sek110237 { 27875184Sek110237 if (help >= 1) 27885184Sek110237 (void) fprintf(stderr, USAGE1, cmdname); 27895184Sek110237 if (help >= 2) { 27905184Sek110237 27915184Sek110237 (void) fprintf(stderr, 27925184Sek110237 "\n'f' language definition:\n\n"); 27935184Sek110237 fileset_usage(); 27945184Sek110237 procflow_usage(); 27955184Sek110237 threadflow_usage(); 27965184Sek110237 flowoplib_usage(); 27975184Sek110237 eventgen_usage(); 27985184Sek110237 (void) fprintf(stderr, PARSER_CMDS); 27995184Sek110237 (void) fprintf(stderr, PARSER_EXAMPLE); 28005184Sek110237 } 28015184Sek110237 exit(E_USAGE); 28025184Sek110237 } 28035184Sek110237 28045184Sek110237 int 28055184Sek110237 yywrap() 28065184Sek110237 { 28075184Sek110237 char buf[1024]; 28085184Sek110237 28095184Sek110237 if (parentscript) { 28105184Sek110237 yyin = parentscript; 28115184Sek110237 yy_switchfilescript(yyin); 28125184Sek110237 parentscript = NULL; 28135184Sek110237 return (0); 28145184Sek110237 } else 28155184Sek110237 return (1); 28165184Sek110237 } 2817