Home | History | Annotate | Download | only in common
      1  5184  ek110237 /*
      2  5184  ek110237  * CDDL HEADER START
      3  5184  ek110237  *
      4  5184  ek110237  * The contents of this file are subject to the terms of the
      5  5184  ek110237  * Common Development and Distribution License (the "License").
      6  5184  ek110237  * You may not use this file except in compliance with the License.
      7  5184  ek110237  *
      8  5184  ek110237  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  5184  ek110237  * or http://www.opensolaris.org/os/licensing.
     10  5184  ek110237  * See the License for the specific language governing permissions
     11  5184  ek110237  * and limitations under the License.
     12  5184  ek110237  *
     13  5184  ek110237  * When distributing Covered Code, include this CDDL HEADER in each
     14  5184  ek110237  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  5184  ek110237  * If applicable, add the following below this CDDL HEADER, with the
     16  5184  ek110237  * fields enclosed by brackets "[]" replaced with your own identifying
     17  5184  ek110237  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  5184  ek110237  *
     19  5184  ek110237  * CDDL HEADER END
     20  5184  ek110237  */
     21  5184  ek110237 /*
     22  8615    Andrew  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  5184  ek110237  * Use is subject to license terms.
     24  5184  ek110237  */
     25  5184  ek110237 
     26  5184  ek110237 #include <stdio.h>
     27  5184  ek110237 #include <fcntl.h>
     28  5184  ek110237 #include <limits.h>
     29  5184  ek110237 #include <time.h>
     30  5184  ek110237 #include <libgen.h>
     31  5184  ek110237 #include <unistd.h>
     32  5184  ek110237 #include <strings.h>
     33  5184  ek110237 #include "filebench.h"
     34  5184  ek110237 #include "ipc.h"
     35  5184  ek110237 #include "eventgen.h"
     36  5184  ek110237 #include "utils.h"
     37  8615    Andrew #include "fsplug.h"
     38  8615    Andrew 
     39  8615    Andrew /* File System functions vector */
     40  8615    Andrew fsplug_func_t *fs_functions_vec;
     41  5184  ek110237 
     42  5184  ek110237 /*
     43  5184  ek110237  * Routines to access high resolution system time, initialize and
     44  6212  aw148015  * shutdown filebench, log filebench run progress and errors, and
     45  6212  aw148015  * access system information strings.
     46  5184  ek110237  */
     47  5184  ek110237 
     48  5184  ek110237 #if !defined(sun) && defined(USE_RDTSC)
     49  5184  ek110237 /*
     50  5184  ek110237  * Lets us use the rdtsc instruction to get highres time.
     51  5184  ek110237  * Thanks to libmicro
     52  5184  ek110237  */
     53  5184  ek110237 uint64_t	cpu_hz = 0;
     54  5184  ek110237 
     55  5184  ek110237 /*
     56  5184  ek110237  * Uses the rdtsc instruction to get high resolution (cpu
     57  5184  ek110237  * clock ticks) time. Only used for non Sun compiles.
     58  5184  ek110237  */
     59  5184  ek110237 __inline__ long long
     60  5184  ek110237 rdtsc(void)
     61  5184  ek110237 {
     62  5184  ek110237 	unsigned long long x;
     63  5184  ek110237 	__asm__ volatile(".byte 0x0f, 0x31" : "=A" (x));
     64  5184  ek110237 	return (x);
     65  5184  ek110237 }
     66  5184  ek110237 
     67  5184  ek110237 /*
     68  5184  ek110237  * Get high resolution time in nanoseconds. This is the version
     69  5184  ek110237  * used when not compiled for Sun systems. It uses rdtsc call to
     70  5184  ek110237  * get clock ticks and converts to nanoseconds
     71  5184  ek110237  */
     72  5184  ek110237 uint64_t
     73  5184  ek110237 gethrtime(void)
     74  5184  ek110237 {
     75  5184  ek110237 	uint64_t hrt;
     76  5184  ek110237 
     77  5184  ek110237 	/* convert to nanosecs and return */
     78  5184  ek110237 	hrt = 1000000000UL * rdtsc() / cpu_hz;
     79  5184  ek110237 	return (hrt);
     80  5184  ek110237 }
     81  5184  ek110237 
     82  5184  ek110237 /*
     83  5184  ek110237  * Gets CPU clock frequency in MHz from cpuinfo file.
     84  5184  ek110237  * Converts to cpu_hz and stores in cpu_hz global uint64_t.
     85  5184  ek110237  * Only used for non Sun compiles.
     86  5184  ek110237  */
     87  5184  ek110237 static uint64_t
     88  5184  ek110237 parse_cpu_hz(void)
     89  5184  ek110237 {
     90  5184  ek110237 	/*
     91  5184  ek110237 	 * Parse the following from /proc/cpuinfo.
     92  5184  ek110237 	 * cpu MHz		: 2191.563
     93  5184  ek110237 	 */
     94  5184  ek110237 	FILE *cpuinfo;
     95  5184  ek110237 	double hertz = -1;
     96  5184  ek110237 	uint64_t hz;
     97  5184  ek110237 
     98  5184  ek110237 	if ((cpuinfo = fopen("/proc/cpuinfo", "r")) == NULL) {
     99  5184  ek110237 		filebench_log(LOG_ERROR, "open /proc/cpuinfo failed: %s",
    100  5184  ek110237 		    strerror(errno));
    101  5184  ek110237 		filebench_shutdown(1);
    102  5184  ek110237 	}
    103  5184  ek110237 	while (!feof(cpuinfo)) {
    104  5184  ek110237 		char buffer[80];
    105  5184  ek110237 
    106  5184  ek110237 		fgets(buffer, 80, cpuinfo);
    107  5184  ek110237 		if (strlen(buffer) == 0) continue;
    108  5184  ek110237 		if (strncasecmp(buffer, "cpu MHz", 7) == 0) {
    109  5184  ek110237 			char *token = strtok(buffer, ":");
    110  5184  ek110237 
    111  5184  ek110237 			if (token != NULL) {
    112  5184  ek110237 				token = strtok((char *)NULL, ":");
    113  5184  ek110237 				hertz = strtod(token, NULL);
    114  5184  ek110237 			}
    115  5184  ek110237 			break;
    116  5184  ek110237 		}
    117  5184  ek110237 	}
    118  5184  ek110237 	hz = hertz * 1000000;
    119  5184  ek110237 
    120  5184  ek110237 	return (hz);
    121  5184  ek110237 }
    122  5184  ek110237 
    123  5184  ek110237 #elif !defined(sun)
    124  5184  ek110237 
    125  5184  ek110237 /*
    126  5184  ek110237  * Get high resolution time in nanoseconds. This is the version
    127  5184  ek110237  * used if compiled for Sun systems. It calls gettimeofday
    128  5184  ek110237  * to get current time and converts it to nanoseconds.
    129  5184  ek110237  */
    130  5184  ek110237 uint64_t
    131  5184  ek110237 gethrtime(void)
    132  5184  ek110237 {
    133  5184  ek110237 	struct timeval tv;
    134  5184  ek110237 	uint64_t hrt;
    135  5184  ek110237 
    136  5184  ek110237 	gettimeofday(&tv, NULL);
    137  5184  ek110237 
    138  5184  ek110237 	hrt = (uint64_t)tv.tv_sec * 1000000000UL +
    139  5184  ek110237 	    (uint64_t)tv.tv_usec * 1000UL;
    140  5184  ek110237 	return (hrt);
    141  5184  ek110237 }
    142  5184  ek110237 #endif
    143  5184  ek110237 
    144  5184  ek110237 /*
    145  5184  ek110237  * Main filebench initialization. Opens the random number
    146  5184  ek110237  * "device" file or shuts down the run if one is not found.
    147  5184  ek110237  * Sets the cpu clock frequency variable or shuts down the
    148  5184  ek110237  * run if one is not found.
    149  5184  ek110237  */
    150  5184  ek110237 void
    151  5184  ek110237 filebench_init(void)
    152  5184  ek110237 {
    153  6212  aw148015 	fb_random_init();
    154  6212  aw148015 
    155  5184  ek110237 #if defined(USE_RDTSC) && (LINUX_PORT)
    156  5184  ek110237 	cpu_hz = parse_cpu_hz();
    157  5184  ek110237 	if (cpu_hz <= 0) {
    158  5184  ek110237 		filebench_log(LOG_ERROR, "Error getting CPU Mhz: %s",
    159  5184  ek110237 		    strerror(errno));
    160  5184  ek110237 		filebench_shutdown(1);
    161  5184  ek110237 	}
    162  5184  ek110237 #endif /* USE_RDTSC */
    163  5184  ek110237 }
    164  5184  ek110237 
    165  5184  ek110237 extern int lex_lineno;
    166  5184  ek110237 
    167  5184  ek110237 /*
    168  5184  ek110237  * Writes a message consisting of information formated by
    169  5184  ek110237  * "fmt" to the log file, dump file or stdout.  The supplied
    170  5184  ek110237  * "level" argument determines which file to write to and
    171  5184  ek110237  * what other actions to take. The level LOG_LOG writes to
    172  5184  ek110237  * the "log" file, and will open the file on the first
    173  5184  ek110237  * invocation. The level LOG_DUMP writes to the "dump" file,
    174  5184  ek110237  * and will open it on the first invocation. Other levels
    175  5184  ek110237  * print to the stdout device, with the amount of information
    176  5184  ek110237  * dependent on the error level and the current error level
    177  6391  aw148015  * setting in filebench_shm->shm_debug_level.
    178  5184  ek110237  */
    179  5184  ek110237 void filebench_log
    180  5184  ek110237 __V((int level, const char *fmt, ...))
    181  5184  ek110237 {
    182  5184  ek110237 	va_list args;
    183  5184  ek110237 	hrtime_t now;
    184  5184  ek110237 	char line[131072];
    185  5184  ek110237 	char buf[131072];
    186  5184  ek110237 
    187  5184  ek110237 	if (level == LOG_FATAL)
    188  5184  ek110237 		goto fatal;
    189  5184  ek110237 
    190  5184  ek110237 	/* open logfile if not already open and writing to it */
    191  5184  ek110237 	if ((level == LOG_LOG) &&
    192  6391  aw148015 	    (filebench_shm->shm_log_fd < 0)) {
    193  5184  ek110237 		char path[MAXPATHLEN];
    194  5184  ek110237 		char *s;
    195  5184  ek110237 
    196  6391  aw148015 		(void) strcpy(path, filebench_shm->shm_fscriptname);
    197  5184  ek110237 		if ((s = strstr(path, ".f")))
    198  5184  ek110237 			*s = 0;
    199  5184  ek110237 		else
    200  5184  ek110237 			(void) strcpy(path, "filebench");
    201  5184  ek110237 
    202  5184  ek110237 		(void) strcat(path, ".csv");
    203  5184  ek110237 
    204  6391  aw148015 		filebench_shm->shm_log_fd =
    205  5184  ek110237 		    open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
    206  5184  ek110237 	}
    207  5184  ek110237 
    208  5184  ek110237 	/*
    209  5184  ek110237 	 * if logfile still not open, switch to LOG_ERROR level so
    210  5184  ek110237 	 * it gets reported to stdout
    211  5184  ek110237 	 */
    212  5184  ek110237 	if ((level == LOG_LOG) &&
    213  6391  aw148015 	    (filebench_shm->shm_log_fd < 0)) {
    214  5184  ek110237 		(void) snprintf(line, sizeof (line),  "Open logfile failed: %s",
    215  5184  ek110237 		    strerror(errno));
    216  5184  ek110237 		level = LOG_ERROR;
    217  5184  ek110237 	}
    218  5184  ek110237 
    219  5184  ek110237 	/* open dumpfile if not already open and writing to it */
    220  5184  ek110237 	if ((level == LOG_DUMP) &&
    221  6391  aw148015 	    (*filebench_shm->shm_dump_filename == 0))
    222  5184  ek110237 		return;
    223  5184  ek110237 
    224  5184  ek110237 	if ((level == LOG_DUMP) &&
    225  6391  aw148015 	    (filebench_shm->shm_dump_fd < 0)) {
    226  5184  ek110237 
    227  6391  aw148015 		filebench_shm->shm_dump_fd =
    228  6391  aw148015 		    open(filebench_shm->shm_dump_filename,
    229  5184  ek110237 		    O_RDWR | O_CREAT | O_TRUNC, 0666);
    230  5184  ek110237 	}
    231  5184  ek110237 
    232  5184  ek110237 	if ((level == LOG_DUMP) &&
    233  6391  aw148015 	    (filebench_shm->shm_dump_fd < 0)) {
    234  5184  ek110237 		(void) snprintf(line, sizeof (line), "Open logfile failed: %s",
    235  5184  ek110237 		    strerror(errno));
    236  5184  ek110237 		level = LOG_ERROR;
    237  5184  ek110237 	}
    238  5184  ek110237 
    239  6084  aw148015 	/* Quit if this is a LOG_ERROR messages and they are disabled */
    240  6084  aw148015 	if ((filebench_shm->shm_1st_err) && (level == LOG_ERROR))
    241  6084  aw148015 		return;
    242  6084  aw148015 
    243  6084  aw148015 	if (level == LOG_ERROR1) {
    244  6084  aw148015 		if (filebench_shm->shm_1st_err)
    245  6084  aw148015 			return;
    246  6084  aw148015 
    247  6084  aw148015 		/* A LOG_ERROR1 temporarily disables LOG_ERROR messages */
    248  6084  aw148015 		filebench_shm->shm_1st_err = 1;
    249  6084  aw148015 		level = LOG_ERROR;
    250  6084  aw148015 	}
    251  6084  aw148015 
    252  5184  ek110237 	/* Only log greater than debug setting */
    253  5184  ek110237 	if ((level != LOG_DUMP) && (level != LOG_LOG) &&
    254  6391  aw148015 	    (level > filebench_shm->shm_debug_level))
    255  5184  ek110237 		return;
    256  5184  ek110237 
    257  5184  ek110237 	now = gethrtime();
    258  5184  ek110237 
    259  5184  ek110237 fatal:
    260  5184  ek110237 
    261  5184  ek110237 #ifdef __STDC__
    262  5184  ek110237 	va_start(args, fmt);
    263  5184  ek110237 #else
    264  5184  ek110237 	char *fmt;
    265  5184  ek110237 	va_start(args);
    266  5184  ek110237 	fmt = va_arg(args, char *);
    267  5184  ek110237 #endif
    268  5184  ek110237 
    269  5184  ek110237 	(void) vsprintf(line, fmt, args);
    270  5184  ek110237 
    271  5184  ek110237 	va_end(args);
    272  5184  ek110237 
    273  5184  ek110237 	if (level == LOG_FATAL) {
    274  6305  aw148015 		(void) fprintf(stderr, "%s\n", line);
    275  5184  ek110237 		return;
    276  5184  ek110237 	}
    277  5184  ek110237 
    278  5184  ek110237 	/* Serialize messages to log */
    279  6391  aw148015 	(void) ipc_mutex_lock(&filebench_shm->shm_msg_lock);
    280  5184  ek110237 
    281  5184  ek110237 	if (level == LOG_LOG) {
    282  6391  aw148015 		if (filebench_shm->shm_log_fd > 0) {
    283  5184  ek110237 			(void) snprintf(buf, sizeof (buf), "%s\n", line);
    284  6391  aw148015 			(void) write(filebench_shm->shm_log_fd, buf,
    285  6391  aw148015 			    strlen(buf));
    286  6391  aw148015 			(void) fsync(filebench_shm->shm_log_fd);
    287  6391  aw148015 			(void) ipc_mutex_unlock(&filebench_shm->shm_msg_lock);
    288  6305  aw148015 			return;
    289  5184  ek110237 		}
    290  5184  ek110237 
    291  5184  ek110237 	} else if (level == LOG_DUMP) {
    292  6391  aw148015 		if (filebench_shm->shm_dump_fd != -1) {
    293  5184  ek110237 			(void) snprintf(buf, sizeof (buf), "%s\n", line);
    294  6391  aw148015 			(void) write(filebench_shm->shm_dump_fd, buf,
    295  6391  aw148015 			    strlen(buf));
    296  6391  aw148015 			(void) fsync(filebench_shm->shm_dump_fd);
    297  6391  aw148015 			(void) ipc_mutex_unlock(&filebench_shm->shm_msg_lock);
    298  6305  aw148015 			return;
    299  5184  ek110237 		}
    300  5184  ek110237 
    301  6391  aw148015 	} else if (filebench_shm->shm_debug_level > LOG_INFO) {
    302  6305  aw148015 		if (level < LOG_INFO)
    303  6305  aw148015 			(void) fprintf(stderr, "%5d: ", (int)my_pid);
    304  6305  aw148015 		else
    305  6305  aw148015 			(void) fprintf(stdout, "%5d: ", (int)my_pid);
    306  6305  aw148015 	}
    307  6305  aw148015 
    308  6305  aw148015 	if (level < LOG_INFO) {
    309  6305  aw148015 		(void) fprintf(stderr, "%4.3f: %s",
    310  6391  aw148015 		    (now - filebench_shm->shm_epoch) / FSECS,
    311  5184  ek110237 		    line);
    312  6305  aw148015 
    313  6305  aw148015 		if (my_procflow == NULL)
    314  6305  aw148015 			(void) fprintf(stderr, " on line %d", lex_lineno);
    315  6305  aw148015 
    316  6305  aw148015 		(void) fprintf(stderr, "\n");
    317  6305  aw148015 		(void) fflush(stderr);
    318  5184  ek110237 	} else {
    319  5184  ek110237 		(void) fprintf(stdout, "%4.3f: %s",
    320  6391  aw148015 		    (now - filebench_shm->shm_epoch) / FSECS,
    321  5184  ek110237 		    line);
    322  5184  ek110237 		(void) fprintf(stdout, "\n");
    323  5184  ek110237 		(void) fflush(stdout);
    324  5184  ek110237 	}
    325  5184  ek110237 
    326  6391  aw148015 	(void) ipc_mutex_unlock(&filebench_shm->shm_msg_lock);
    327  5184  ek110237 }
    328  5184  ek110237 
    329  5184  ek110237 /*
    330  5184  ek110237  * Stops the run and exits filebench. If filebench is
    331  5184  ek110237  * currently running a workload, calls procflow_shutdown()
    332  5184  ek110237  * to stop the run. Also closes and deletes shared memory.
    333  5184  ek110237  */
    334  5184  ek110237 void
    335  5184  ek110237 filebench_shutdown(int error) {
    336  6391  aw148015 
    337  6391  aw148015 	if (error) {
    338  9801    Andrew 		filebench_log(LOG_DEBUG_IMPL, "Shutdown on error %d", error);
    339  9326    Andrew 		(void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock);
    340  9326    Andrew 		if (filebench_shm->shm_f_abort == FILEBENCH_ABORT_FINI) {
    341  9326    Andrew 			(void) ipc_mutex_unlock(
    342  9326    Andrew 			    &filebench_shm->shm_procflow_lock);
    343  9326    Andrew 			return;
    344  9326    Andrew 		}
    345  6391  aw148015 		filebench_shm->shm_f_abort = FILEBENCH_ABORT_ERROR;
    346  9326    Andrew 		(void) ipc_mutex_unlock(&filebench_shm->shm_procflow_lock);
    347  6391  aw148015 	} else {
    348  6391  aw148015 		filebench_log(LOG_DEBUG_IMPL, "Shutdown");
    349  6391  aw148015 	}
    350  6391  aw148015 
    351  6701  aw148015 	procflow_shutdown();
    352  6391  aw148015 
    353  6391  aw148015 	(void) unlink("/tmp/filebench_shm");
    354  5184  ek110237 	ipc_ismdelete();
    355  5184  ek110237 	exit(error);
    356  5184  ek110237 }
    357  5184  ek110237 
    358  5184  ek110237 /*
    359  5184  ek110237  * Put the hostname in ${hostname}. The system supplied
    360  5184  ek110237  * host name string is copied into an allocated string and
    361  5184  ek110237  * the pointer to the string is placed in the supplied
    362  6212  aw148015  * variable "var". If var->var_val.string already points to
    363  5184  ek110237  * a string, the string is freed. The routine always
    364  5184  ek110237  * returns zero (0).
    365  5184  ek110237  */
    366  5184  ek110237 var_t *
    367  5184  ek110237 host_var(var_t *var)
    368  5184  ek110237 {
    369  5184  ek110237 	char hoststr[128];
    370  6212  aw148015 	char *strptr;
    371  5184  ek110237 
    372  5184  ek110237 	(void) gethostname(hoststr, 128);
    373  6212  aw148015 	if (VAR_HAS_STRING(var) && var->var_val.string)
    374  6212  aw148015 		free(var->var_val.string);
    375  6212  aw148015 
    376  6212  aw148015 	if ((strptr = fb_stralloc(hoststr)) == NULL) {
    377  6212  aw148015 		filebench_log(LOG_ERROR,
    378  6212  aw148015 		    "unable to allocate string for host name");
    379  6212  aw148015 		return (NULL);
    380  6212  aw148015 	}
    381  6212  aw148015 
    382  6212  aw148015 	VAR_SET_STR(var, strptr);
    383  5184  ek110237 	return (0);
    384  5184  ek110237 }
    385  5184  ek110237 
    386  5184  ek110237 /*
    387  5184  ek110237  * Put the date string in ${date}. The system supplied date is
    388  5184  ek110237  * copied into an allocated string and the pointer to the string
    389  6212  aw148015  * is placed in the supplied var_t's var_val.string. If
    390  6212  aw148015  * var->var_val.string already points to a string, the string
    391  6212  aw148015  * is freed. The routine returns a pointer to the supplied var_t,
    392  6212  aw148015  * unless it is unable to allocate string for the date, in which
    393  6212  aw148015  * case it returns NULL.
    394  5184  ek110237  */
    395  5184  ek110237 var_t *
    396  5184  ek110237 date_var(var_t *var)
    397  5184  ek110237 {
    398  5184  ek110237 	char datestr[128];
    399  6212  aw148015 	char *strptr;
    400  5184  ek110237 #ifdef HAVE_CFTIME
    401  5184  ek110237 	time_t t = time(NULL);
    402  5184  ek110237 #else
    403  5184  ek110237 	struct tm t;
    404  5184  ek110237 #endif
    405  5184  ek110237 
    406  5184  ek110237 #ifdef HAVE_CFTIME
    407  5184  ek110237 	cftime(datestr, "%y%m%d%H" "%M", &t);
    408  5184  ek110237 #else
    409  5184  ek110237 	(void) strftime(datestr, sizeof (datestr), "%y%m%d%H %M", &t);
    410  5184  ek110237 #endif
    411  5184  ek110237 
    412  6212  aw148015 	if (VAR_HAS_STRING(var) && var->var_val.string)
    413  6212  aw148015 		free(var->var_val.string);
    414  6212  aw148015 
    415  6212  aw148015 	if ((strptr = fb_stralloc(datestr)) == NULL) {
    416  6212  aw148015 		filebench_log(LOG_ERROR,
    417  6212  aw148015 		    "unable to allocate string for date");
    418  6212  aw148015 		return (NULL);
    419  6212  aw148015 	}
    420  6212  aw148015 
    421  6212  aw148015 	VAR_SET_STR(var, strptr);
    422  5184  ek110237 
    423  5184  ek110237 	return (var);
    424  5184  ek110237 }
    425  5184  ek110237 
    426  5184  ek110237 extern char *fscriptname;
    427  5184  ek110237 
    428  5184  ek110237 /*
    429  5184  ek110237  * Put the script name in ${script}. The path name of the script
    430  5184  ek110237  * used with this filebench run trimmed of the trailing ".f" and
    431  5184  ek110237  * all leading subdirectories. The remaining script name is
    432  6212  aw148015  * copied into the var_val.string field of the supplied variable
    433  6212  aw148015  * "var". The routine returns a pointer to the supplied var_t,
    434  6212  aw148015  * unless it is unable to allocate string space, in which case it
    435  6212  aw148015  * returns NULL.
    436  5184  ek110237  */
    437  5184  ek110237 var_t *
    438  5184  ek110237 script_var(var_t *var)
    439  5184  ek110237 {
    440  5184  ek110237 	char *scriptstr;
    441  5184  ek110237 	char *f = fb_stralloc(fscriptname);
    442  6212  aw148015 	char *strptr;
    443  5184  ek110237 
    444  5184  ek110237 	/* Trim the .f suffix */
    445  5184  ek110237 	for (scriptstr = f + strlen(f) - 1; scriptstr != f; scriptstr--) {
    446  5184  ek110237 		if (*scriptstr == '.') {
    447  5184  ek110237 			*scriptstr = 0;
    448  5184  ek110237 			break;
    449  5184  ek110237 		}
    450  5184  ek110237 	}
    451  5184  ek110237 
    452  6212  aw148015 	if ((strptr = fb_stralloc(basename(f))) == NULL) {
    453  6212  aw148015 		filebench_log(LOG_ERROR,
    454  6212  aw148015 		    "unable to allocate string for script name");
    455  6212  aw148015 		free(f);
    456  6212  aw148015 		return (NULL);
    457  6212  aw148015 	}
    458  6212  aw148015 
    459  6212  aw148015 	VAR_SET_STR(var, strptr);
    460  5184  ek110237 	free(f);
    461  5184  ek110237 
    462  5184  ek110237 	return (var);
    463  5184  ek110237 }
    464  8615    Andrew 
    465  8615    Andrew void fb_lfs_funcvecinit(void);
    466  8615    Andrew 
    467  8615    Andrew /*
    468  8615    Andrew  * Initialize any "plug-in" I/O function vectors. Called by each
    469  8615    Andrew  * filebench process that is forked, as the vector is relative to
    470  8615    Andrew  * its image.
    471  8615    Andrew  */
    472  8615    Andrew void
    473  8615    Andrew filebench_plugin_funcvecinit(void)
    474  8615    Andrew {
    475  8615    Andrew 
    476  8615    Andrew 	switch (filebench_shm->shm_filesys_type) {
    477  8615    Andrew 	case LOCAL_FS_PLUG:
    478  8615    Andrew 		fb_lfs_funcvecinit();
    479  8615    Andrew 		break;
    480  8615    Andrew 
    481  8615    Andrew 	case NFS3_PLUG:
    482  8615    Andrew 	case NFS4_PLUG:
    483  8615    Andrew 	case CIFS_PLUG:
    484  8615    Andrew 		break;
    485  8615    Andrew 	default:
    486  8615    Andrew 		filebench_log(LOG_ERROR,
    487  8615    Andrew 		    "filebench_plugin_funcvecinit: unknown file system");
    488  8615    Andrew 		break;
    489  8615    Andrew 	}
    490  8615    Andrew }
    491