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