diff options
author | aw148015 <Andrew.W.Wilson@sun.com> | 2009-01-26 09:32:31 -0800 |
---|---|---|
committer | aw148015 <Andrew.W.Wilson@sun.com> | 2009-01-26 09:32:31 -0800 |
commit | 4432feae5fd55150d54ce309a84a0a321b4d5449 (patch) | |
tree | 47c44a6b0775df40dc750359bd6ee22c218c2041 /usr/src | |
parent | edd20d23d143338b5e74d55a15257d4cccac7523 (diff) | |
download | illumos-joyent-4432feae5fd55150d54ce309a84a0a321b4d5449.tar.gz |
6792062 FileBench needs work to allow plug-in file system clients
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/filebench/Makefile.com | 5 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/fb_localfs.c | 682 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/filebench.h | 5 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/fileset.c | 84 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/fileset.h | 7 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/flowop.c | 93 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/flowop.h | 19 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/flowop_library.c | 599 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/fsplug.h | 144 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/ipc.h | 14 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/misc.c | 37 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/parser_gram.y | 12 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/procflow.c | 5 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/threadflow.c | 5 | ||||
-rw-r--r-- | usr/src/cmd/filebench/common/threadflow.h | 7 | ||||
-rw-r--r-- | usr/src/cmd/filebench/config/Makefile | 5 | ||||
-rw-r--r-- | usr/src/cmd/filebench/config/newfeatures.prof | 86 | ||||
-rw-r--r-- | usr/src/pkgdefs/SUNWfilebench/prototype_com | 3 |
18 files changed, 1251 insertions, 561 deletions
diff --git a/usr/src/cmd/filebench/Makefile.com b/usr/src/cmd/filebench/Makefile.com index e583cbd054..173fdd5030 100644 --- a/usr/src/cmd/filebench/Makefile.com +++ b/usr/src/cmd/filebench/Makefile.com @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -31,8 +31,9 @@ include ../../Makefile.targ SRCS = \ auto_comp.c \ eventgen.c \ - fb_random.c \ fb_avl.c \ + fb_localfs.c \ + fb_random.c \ fileset.c \ flowop.c \ flowop_library.c \ diff --git a/usr/src/cmd/filebench/common/fb_localfs.c b/usr/src/cmd/filebench/common/fb_localfs.c new file mode 100644 index 0000000000..ff62bb1114 --- /dev/null +++ b/usr/src/cmd/filebench/common/fb_localfs.c @@ -0,0 +1,682 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + * Portions Copyright 2008 Denis Cheng + */ + +#include "config.h" +#include "filebench.h" +#include "flowop.h" +#include "threadflow.h" /* For aiolist definition */ + +#ifndef HAVE_OFF64_T +/* + * We are probably on linux. + * According to http://www.suse.de/~aj/linux_lfs.html, defining the + * above, automatically changes type of off_t to off64_t. so let + * us use only off_t as off64_t is not defined + */ +#defineoff64_t off_t +#endif /* HAVE_OFF64_T */ + +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <libgen.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/resource.h> + +#include "filebench.h" +#include "fsplug.h" + +#ifdef HAVE_AIO +#include <aio.h> +#endif /* HAVE_AIO */ + +#ifdef HAVE_LIBAIO_H +#include <libaio.h> +#endif /* HAVE_LIBAIO_H */ + +#ifndef HAVE_AIOCB64_T +#define aiocb64 aiocb +#endif /* HAVE_AIOCB64_T */ + +/* + * These routines implement local file access. They are placed into a + * vector of functions that are called by all I/O operations in fileset.c + * and flowop_library.c. This represents the default file system plug-in, + * and may be replaced by vectors for other file system plug-ins. + */ + +static int fb_lfs_freemem(fb_fdesc_t *fd, off64_t size); +static int fb_lfs_open(fb_fdesc_t *, char *, int, int); +static int fb_lfs_pread(fb_fdesc_t *, caddr_t, fbint_t, off64_t); +static int fb_lfs_read(fb_fdesc_t *, caddr_t, fbint_t); +static int fb_lfs_pwrite(fb_fdesc_t *, caddr_t, fbint_t, off64_t); +static int fb_lfs_write(fb_fdesc_t *, caddr_t, fbint_t); +static int fb_lfs_lseek(fb_fdesc_t *, off64_t, int); +static int fb_lfs_truncate(fb_fdesc_t *, off64_t); +static int fb_lfs_rename(const char *, const char *); +static int fb_lfs_close(fb_fdesc_t *); +static int fb_lfs_link(const char *, const char *); +static int fb_lfs_symlink(const char *, const char *); +static int fb_lfs_unlink(char *); +static ssize_t fb_lfs_readlink(const char *, char *, size_t); +static int fb_lfs_mkdir(char *, int); +static int fb_lfs_rmdir(char *); +static DIR *fb_lfs_opendir(char *); +static struct dirent *fb_lfs_readdir(DIR *); +static int fb_lfs_closedir(DIR *); +static int fb_lfs_fsync(fb_fdesc_t *); +static int fb_lfs_stat(char *, struct stat64 *); +static int fb_lfs_fstat(fb_fdesc_t *, struct stat64 *); +static int fb_lfs_access(const char *, int); + +static fsplug_func_t fb_lfs_funcs = +{ + "locfs", + fb_lfs_freemem, /* flush page cache */ + fb_lfs_open, /* open */ + fb_lfs_pread, /* pread */ + fb_lfs_read, /* read */ + fb_lfs_pwrite, /* pwrite */ + fb_lfs_write, /* write */ + fb_lfs_lseek, /* lseek */ + fb_lfs_truncate, /* ftruncate */ + fb_lfs_rename, /* rename */ + fb_lfs_close, /* close */ + fb_lfs_link, /* link */ + fb_lfs_symlink, /* symlink */ + fb_lfs_unlink, /* unlink */ + fb_lfs_readlink, /* readlink */ + fb_lfs_mkdir, /* mkdir */ + fb_lfs_rmdir, /* rmdir */ + fb_lfs_opendir, /* opendir */ + fb_lfs_readdir, /* readdir */ + fb_lfs_closedir, /* closedir */ + fb_lfs_fsync, /* fsync */ + fb_lfs_stat, /* stat */ + fb_lfs_fstat, /* fstat */ + fb_lfs_access /* access */ +}; + +#ifdef HAVE_AIO +/* + * Local file system asynchronous IO flowops are in this module, as + * they have a number of local file system specific features. + */ +static int fb_lfsflow_aiowrite(threadflow_t *threadflow, flowop_t *flowop); +static int fb_lfsflow_aiowait(threadflow_t *threadflow, flowop_t *flowop); + +static flowop_proto_t fb_lfsflow_funcs[] = { + FLOW_TYPE_AIO, FLOW_ATTR_WRITE, "aiowrite", flowop_init_generic, + fb_lfsflow_aiowrite, flowop_destruct_generic, + FLOW_TYPE_AIO, 0, "aiowait", flowop_init_generic, + fb_lfsflow_aiowait, flowop_destruct_generic +}; + +#endif /* HAVE_AIO */ + +/* + * Initialize this processes I/O functions vector to point to + * the vector of local file system I/O functions + */ +void +fb_lfs_funcvecinit(void) +{ + fs_functions_vec = &fb_lfs_funcs; +} + +/* + * Initialize those flowops whose implementation is file system + * specific. + */ +void +fb_lfs_flowinit(void) +{ + int nops; + + /* + * re-initialize the I/O functions vector while we are at + * it as it may have been redefined since the process was + * created, at least if this is the master processes + */ + fb_lfs_funcvecinit(); + +#ifdef HAVE_AIO + nops = sizeof (fb_lfsflow_funcs) / sizeof (flowop_proto_t); + flowop_flow_init(fb_lfsflow_funcs, nops); +#endif /* HAVE_AIO */ +} + +/* + * Frees up memory mapped file region of supplied size. The + * file descriptor "fd" indicates which memory mapped file. + * If successful, returns 0. Otherwise returns -1 if "size" + * is zero, or -1 times the number of times msync() failed. + */ +static int +fb_lfs_freemem(fb_fdesc_t *fd, off64_t size) +{ + off64_t left; + int ret = 0; + + for (left = size; left > 0; left -= MMAP_SIZE) { + off64_t thismapsize; + caddr_t addr; + + thismapsize = MIN(MMAP_SIZE, left); + addr = mmap64(0, thismapsize, PROT_READ|PROT_WRITE, + MAP_SHARED, fd->fd_num, size - left); + ret += msync(addr, thismapsize, MS_INVALIDATE); + (void) munmap(addr, thismapsize); + } + return (ret); +} + +/* + * Does a posix pread. Returns what the pread() returns. + */ +static int +fb_lfs_pread(fb_fdesc_t *fd, caddr_t iobuf, fbint_t iosize, off64_t fileoffset) +{ + return (pread64(fd->fd_num, iobuf, iosize, fileoffset)); +} + +/* + * Does a posix read. Returns what the read() returns. + */ +static int +fb_lfs_read(fb_fdesc_t *fd, caddr_t iobuf, fbint_t iosize) +{ + return (read(fd->fd_num, iobuf, iosize)); +} + +#ifdef HAVE_AIO + +/* + * Asynchronous write section. An Asynchronous IO element + * (aiolist_t) is used to associate the asynchronous write request with + * its subsequent completion. This element includes a aiocb64 struct + * that is used by posix aio_xxx calls to track the asynchronous writes. + * The flowops aiowrite and aiowait result in calls to these posix + * aio_xxx system routines to do the actual asynchronous write IO + * operations. + */ + + +/* + * Allocates an asynchronous I/O list (aio, of type + * aiolist_t) element. Adds it to the flowop thread's + * threadflow aio list. Returns a pointer to the element. + */ +static aiolist_t * +aio_allocate(flowop_t *flowop) +{ + aiolist_t *aiolist; + + if ((aiolist = malloc(sizeof (aiolist_t))) == NULL) { + filebench_log(LOG_ERROR, "malloc aiolist failed"); + filebench_shutdown(1); + } + + /* Add to list */ + if (flowop->fo_thread->tf_aiolist == NULL) { + flowop->fo_thread->tf_aiolist = aiolist; + aiolist->al_next = NULL; + } else { + aiolist->al_next = flowop->fo_thread->tf_aiolist; + flowop->fo_thread->tf_aiolist = aiolist; + } + return (aiolist); +} + +/* + * Searches for the aiolist element that has a matching + * completion block, aiocb. If none found returns FILEBENCH_ERROR. If + * found, removes the aiolist element from flowop thread's + * list and returns FILEBENCH_OK. + */ +static int +aio_deallocate(flowop_t *flowop, struct aiocb64 *aiocb) +{ + aiolist_t *aiolist = flowop->fo_thread->tf_aiolist; + aiolist_t *previous = NULL; + aiolist_t *match = NULL; + + if (aiocb == NULL) { + filebench_log(LOG_ERROR, "null aiocb deallocate"); + return (FILEBENCH_OK); + } + + while (aiolist) { + if (aiocb == &(aiolist->al_aiocb)) { + match = aiolist; + break; + } + previous = aiolist; + aiolist = aiolist->al_next; + } + + if (match == NULL) + return (FILEBENCH_ERROR); + + /* Remove from the list */ + if (previous) + previous->al_next = match->al_next; + else + flowop->fo_thread->tf_aiolist = match->al_next; + + return (FILEBENCH_OK); +} + +/* + * Emulate posix aiowrite(). Determines which file to use, + * either one file of a fileset, or the file associated + * with a fileobj, allocates and fills an aiolist_t element + * for the write, and issues the asynchronous write. This + * operation is only valid for random IO, and returns an + * error if the flowop is set for sequential IO. Returns + * FILEBENCH_OK on success, FILEBENCH_NORSC if iosetup can't + * obtain a file to open, and FILEBENCH_ERROR on any + * encountered error. + */ +static int +fb_lfsflow_aiowrite(threadflow_t *threadflow, flowop_t *flowop) +{ + caddr_t iobuf; + fbint_t wss; + fbint_t iosize; + fb_fdesc_t *fdesc; + int ret; + + iosize = avd_get_int(flowop->fo_iosize); + + if ((ret = flowoplib_iosetup(threadflow, flowop, &wss, &iobuf, + &fdesc, iosize)) != FILEBENCH_OK) + return (ret); + + if (avd_get_bool(flowop->fo_random)) { + uint64_t fileoffset; + struct aiocb64 *aiocb; + aiolist_t *aiolist; + + if (filebench_randomno64(&fileoffset, + wss, iosize, NULL) == -1) { + filebench_log(LOG_ERROR, + "file size smaller than IO size for thread %s", + flowop->fo_name); + return (FILEBENCH_ERROR); + } + + aiolist = aio_allocate(flowop); + aiolist->al_type = AL_WRITE; + aiocb = &aiolist->al_aiocb; + + aiocb->aio_fildes = fdesc->fd_num; + aiocb->aio_buf = iobuf; + aiocb->aio_nbytes = (size_t)iosize; + aiocb->aio_offset = (off64_t)fileoffset; + aiocb->aio_reqprio = 0; + + filebench_log(LOG_DEBUG_IMPL, + "aio fd=%d, bytes=%llu, offset=%llu", + fdesc->fd_num, (u_longlong_t)iosize, + (u_longlong_t)fileoffset); + + flowop_beginop(threadflow, flowop); + if (aio_write64(aiocb) < 0) { + filebench_log(LOG_ERROR, "aiowrite failed: %s", + strerror(errno)); + filebench_shutdown(1); + } + flowop_endop(threadflow, flowop, iosize); + } else { + return (FILEBENCH_ERROR); + } + + return (FILEBENCH_OK); +} + + + +#define MAXREAP 4096 + +/* + * Emulate posix aiowait(). Waits for the completion of half the + * outstanding asynchronous IOs, or a single IO, which ever is + * larger. The routine will return after a sufficient number of + * completed calls issued by any thread in the procflow have + * completed, or a 1 second timout elapses. All completed + * IO operations are deleted from the thread's aiolist. + */ +static int +fb_lfsflow_aiowait(threadflow_t *threadflow, flowop_t *flowop) +{ + struct aiocb64 **worklist; + aiolist_t *aio = flowop->fo_thread->tf_aiolist; + int uncompleted = 0; + + worklist = calloc(MAXREAP, sizeof (struct aiocb64 *)); + + /* Count the list of pending aios */ + while (aio) { + uncompleted++; + aio = aio->al_next; + } + + do { + uint_t ncompleted = 0; + uint_t todo; + struct timespec timeout; + int inprogress; + int i; + + /* Wait for half of the outstanding requests */ + timeout.tv_sec = 1; + timeout.tv_nsec = 0; + + if (uncompleted > MAXREAP) + todo = MAXREAP; + else + todo = uncompleted / 2; + + if (todo == 0) + todo = 1; + + flowop_beginop(threadflow, flowop); + +#ifdef HAVE_AIOWAITN + if (((aio_waitn64((struct aiocb64 **)worklist, + MAXREAP, &todo, &timeout)) == -1) && + errno && (errno != ETIME)) { + filebench_log(LOG_ERROR, + "aiowait failed: %s, outstanding = %d, " + "ncompleted = %d ", + strerror(errno), uncompleted, todo); + } + + ncompleted = todo; + /* Take the completed I/Os from the list */ + inprogress = 0; + for (i = 0; i < ncompleted; i++) { + if ((aio_return64(worklist[i]) == -1) && + (errno == EINPROGRESS)) { + inprogress++; + continue; + } + if (aio_deallocate(flowop, worklist[i]) + == FILEBENCH_ERROR) { + filebench_log(LOG_ERROR, "Could not remove " + "aio from list "); + flowop_endop(threadflow, flowop, 0); + return (FILEBENCH_ERROR); + } + } + + uncompleted -= ncompleted; + uncompleted += inprogress; + +#else + + for (ncompleted = 0, inprogress = 0, + aio = flowop->fo_thread->tf_aiolist; + ncompleted < todo, aio != NULL; aio = aio->al_next) { + int result = aio_error64(aio->al_aiocb); + + if (result == EINPROGRESS) { + inprogress++; + continue; + } + + if ((aio_return64(aio->al_aiocb) == -1) || result) { + filebench_log(LOG_ERROR, "aio failed: %s", + strerror(result)); + continue; + } + + ncompleted++; + + if (aio_deallocate(flowop, &aio->al_aiocb) < 0) { + filebench_log(LOG_ERROR, "Could not remove " + aio from list "); + flowop_endop(threadflow, flowop, 0); + return (FILEBENCH_ERROR); + } + } + + uncompleted -= ncompleted; + +#endif + filebench_log(LOG_DEBUG_SCRIPT, + "aio2 completed %d ios, uncompleted = %d, inprogress = %d", + ncompleted, uncompleted, inprogress); + + } while (uncompleted > MAXREAP); + + flowop_endop(threadflow, flowop, 0); + + free(worklist); + + return (FILEBENCH_OK); +} + +#endif /* HAVE_AIO */ + +/* + * Does an open64 of a file. Inserts the file descriptor number returned + * by open() into the supplied filebench fd. Returns FILEBENCH_OK on + * successs, and FILEBENCH_ERROR on failure. + */ + +static int +fb_lfs_open(fb_fdesc_t *fd, char *path, int flags, int perms) +{ + if ((fd->fd_num = open64(path, flags, perms)) < 0) + return (FILEBENCH_ERROR); + else + return (FILEBENCH_OK); +} + +/* + * Does an unlink (delete) of a file. + */ +static int +fb_lfs_unlink(char *path) +{ + return (unlink(path)); +} + +/* + * Does a readlink of a symbolic link. + */ +static ssize_t +fb_lfs_readlink(const char *path, char *buf, size_t buf_size) +{ + return (readlink(path, buf, buf_size)); +} + +/* + * Does fsync of a file. Returns with fsync return info. + */ +static int +fb_lfs_fsync(fb_fdesc_t *fd) +{ + return (fsync(fd->fd_num)); +} + +/* + * Do a posix lseek of a file. Return what lseek() returns. + */ +static int +fb_lfs_lseek(fb_fdesc_t *fd, off64_t offset, int whence) +{ + return (lseek64(fd->fd_num, offset, whence)); +} + +/* + * Do a posix rename of a file. Return what rename() returns. + */ +static int +fb_lfs_rename(const char *old, const char *new) +{ + return (rename(old, new)); +} + + +/* + * Do a posix close of a file. Return what close() returns. + */ +static int +fb_lfs_close(fb_fdesc_t *fd) +{ + return (close(fd->fd_num)); +} + +/* + * Use mkdir to create a directory. + */ +static int +fb_lfs_mkdir(char *path, int perm) +{ + return (mkdir(path, perm)); +} + +/* + * Use rmdir to delete a directory. Returns what rmdir() returns. + */ +static int +fb_lfs_rmdir(char *path) +{ + return (rmdir(path)); +} + +/* + * Does a posix opendir(), Returns a directory handle on success, + * NULL on failure. + */ +static DIR * +fb_lfs_opendir(char *path) +{ + return (opendir(path)); +} + +/* + * Does a readdir() call. Returns a pointer to a table of directory + * information on success, NULL on failure. + */ +static struct dirent * +fb_lfs_readdir(DIR *dirp) +{ + return (readdir(dirp)); +} + +/* + * Does a closedir() call. + */ +static int +fb_lfs_closedir(DIR *dirp) +{ + return (closedir(dirp)); +} + +/* + * Does an fstat of a file. + */ +static int +fb_lfs_fstat(fb_fdesc_t *fd, struct stat64 *statbufp) +{ + return (fstat64(fd->fd_num, statbufp)); +} + +/* + * Does a stat of a file. + */ +static int +fb_lfs_stat(char *path, struct stat64 *statbufp) +{ + return (stat64(path, statbufp)); +} + +/* + * Do a pwrite64 to a file. + */ +static int +fb_lfs_pwrite(fb_fdesc_t *fd, caddr_t iobuf, fbint_t iosize, off64_t offset) +{ + return (pwrite64(fd->fd_num, iobuf, iosize, offset)); +} + +/* + * Do a write to a file. + */ +static int +fb_lfs_write(fb_fdesc_t *fd, caddr_t iobuf, fbint_t iosize) +{ + return (write(fd->fd_num, iobuf, iosize)); +} + +/* + * Does a truncate operation and returns the result + */ +static int +fb_lfs_truncate(fb_fdesc_t *fd, off64_t fse_size) +{ +#ifdef HAVE_FTRUNCATE64 + return (ftruncate64(fd->fd_num, fse_size)); +#else + return (ftruncate(fd->fd_num, (off_t)fse_size)); +#endif +} + +/* + * Does a link operation and returns the result + */ +static int +fb_lfs_link(const char *existing, const char *new) +{ + return (link(existing, new)); +} + +/* + * Does a symlink operation and returns the result + */ +static int +fb_lfs_symlink(const char *existing, const char *new) +{ + return (symlink(existing, new)); +} + +/* + * Does an access() check on a file. + */ +static int +fb_lfs_access(const char *path, int amode) +{ + return (access(path, amode)); +} diff --git a/usr/src/cmd/filebench/common/filebench.h b/usr/src/cmd/filebench/common/filebench.h index 91da9418e3..8a6b785679 100644 --- a/usr/src/cmd/filebench/common/filebench.h +++ b/usr/src/cmd/filebench/common/filebench.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Portions Copyright 2008 Denis Cheng @@ -91,6 +91,7 @@ extern int noproc; void filebench_init(); void filebench_log __V((int level, const char *fmt, ...)); void filebench_shutdown(int error); +void filebench_plugin_funcvecinit(void); #ifndef HAVE_UINT64_MAX #define UINT64_MAX (((off64_t)1UL<<63UL) - 1UL) @@ -117,7 +118,7 @@ void filebench_shutdown(int error); #define MIN(x, y) ((x) < (y) ? (x) : (y)) #endif -#define FILEBENCH_VERSION "1.4.2" +#define FILEBENCH_VERSION "1.4.3" #define FILEBENCHDIR "/usr/benchmarks/filebench" #define FILEBENCH_PROMPT "filebench> " #define MAX_LINE_LEN 1024 diff --git a/usr/src/cmd/filebench/common/fileset.c b/usr/src/cmd/filebench/common/fileset.c index 86d1e3efd5..64333a561f 100644 --- a/usr/src/cmd/filebench/common/fileset.c +++ b/usr/src/cmd/filebench/common/fileset.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Portions Copyright 2008 Denis Cheng @@ -37,6 +37,7 @@ #include "fileset.h" #include "gamma_dist.h" #include "utils.h" +#include "fsplug.h" /* * File sets, of type fileset_t, are entities which contain @@ -130,31 +131,6 @@ fileset_usage(void) } /* - * Frees up memory mapped file region of supplied size. The - * file descriptor "fd" indicates which memory mapped file. - * If successful, returns 0. Otherwise returns -1 if "size" - * is zero, or -1 times the number of times msync() failed. - */ -static int -fileset_freemem(int fd, off64_t size) -{ - off64_t left; - int ret = 0; - - for (left = size; left > 0; left -= MMAP_SIZE) { - off64_t thismapsize; - caddr_t addr; - - thismapsize = MIN(MMAP_SIZE, left); - addr = mmap64(0, thismapsize, PROT_READ|PROT_WRITE, - MAP_SHARED, fd, size - left); - ret += msync(addr, thismapsize, MS_INVALIDATE); - (void) munmap(addr, thismapsize); - } - return (ret); -} - -/* * Creates a path string from the filesetentry_t "*entry" * and all of its parent's path names. The resulting path * is a concatination of all the individual parent paths. @@ -222,7 +198,7 @@ fileset_mkdir(char *path, int mode) /* Make the directories, from closest to root downwards. */ for (--i; i >= 0; i--) { - (void) mkdir(dirs[i], mode); + (void) FB_MKDIR(dirs[i], mode); free(dirs[i]); } @@ -304,7 +280,7 @@ fileset_alloc_leafdir(filesetentry_t *entry) if (!((entry->fse_flags & FSE_REUSING) && (stat64(path, &sb) == 0))) { /* No file or not reusing, so create */ - if (mkdir(path, 0755) < 0) { + if (FB_MKDIR(path, 0755) < 0) { filebench_log(LOG_ERROR, "Failed to pre-allocate leaf directory %s: %s", path, strerror(errno)); @@ -331,7 +307,7 @@ fileset_alloc_file(filesetentry_t *entry) struct stat64 sb; char *pathtmp; off64_t seek; - int fd; + fb_fdesc_t fdesc; fileset = entry->fse_fileset; (void) fb_strlcpy(path, avd_get_str(fileset->fs_path), MAXPATHLEN); @@ -344,8 +320,8 @@ fileset_alloc_file(filesetentry_t *entry) filebench_log(LOG_DEBUG_IMPL, "Populated %s", entry->fse_path); /* see if reusing and this file exists */ - if ((entry->fse_flags & FSE_REUSING) && (stat64(path, &sb) == 0)) { - if ((fd = open64(path, O_RDWR)) < 0) { + if ((entry->fse_flags & FSE_REUSING) && (FB_STAT(path, &sb) == 0)) { + if (FB_OPEN(&fdesc, path, O_RDWR, 0) == FILEBENCH_ERROR) { filebench_log(LOG_INFO, "Attempted but failed to Re-use file %s", path); @@ -358,10 +334,9 @@ fileset_alloc_file(filesetentry_t *entry) "Re-using file %s", path); if (!avd_get_bool(fileset->fs_cached)) - (void) fileset_freemem(fd, - entry->fse_size); + (void) FB_FREEMEM(&fdesc, entry->fse_size); - (void) close(fd); + (void) FB_CLOSE(&fdesc); /* unbusy the allocated entry */ fileset_unbusy(entry, TRUE, TRUE, 0); @@ -372,17 +347,12 @@ fileset_alloc_file(filesetentry_t *entry) filebench_log(LOG_DEBUG_IMPL, "Truncating & re-using file %s", path); -#ifdef HAVE_FTRUNCATE64 - (void) ftruncate64(fd, (off64_t)entry->fse_size); -#else - (void) ftruncate(fd, (off_t)entry->fse_size); -#endif + (void) FB_FTRUNC(&fdesc, (off64_t)entry->fse_size); if (!avd_get_bool(fileset->fs_cached)) - (void) fileset_freemem(fd, - entry->fse_size); + (void) FB_FREEMEM(&fdesc, entry->fse_size); - (void) close(fd); + (void) FB_CLOSE(&fdesc); /* unbusy the allocated entry */ fileset_unbusy(entry, TRUE, TRUE, 0); @@ -391,7 +361,8 @@ fileset_alloc_file(filesetentry_t *entry) } else { /* No file or not reusing, so create */ - if ((fd = open64(path, O_RDWR | O_CREAT, 0644)) < 0) { + if (FB_OPEN(&fdesc, path, O_RDWR | O_CREAT, 0644) == + FILEBENCH_ERROR) { filebench_log(LOG_ERROR, "Failed to pre-allocate file %s: %s", path, strerror(errno)); @@ -418,12 +389,12 @@ fileset_alloc_file(filesetentry_t *entry) */ wsize = MIN(entry->fse_size - seek, FILE_ALLOC_BLOCK); - ret = write(fd, buf, wsize); + ret = FB_WRITE(&fdesc, buf, wsize); if (ret != wsize) { filebench_log(LOG_ERROR, "Failed to pre-allocate file %s: %s", path, strerror(errno)); - (void) close(fd); + (void) FB_CLOSE(&fdesc); free(buf); fileset_unbusy(entry, TRUE, FALSE, 0); return (FILEBENCH_ERROR); @@ -432,9 +403,9 @@ fileset_alloc_file(filesetentry_t *entry) } if (!avd_get_bool(fileset->fs_cached)) - (void) fileset_freemem(fd, entry->fse_size); + (void) FB_FREEMEM(&fdesc, entry->fse_size); - (void) close(fd); + (void) FB_CLOSE(&fdesc); free(buf); @@ -478,17 +449,17 @@ fileset_alloc_thread(filesetentry_t *entry) * and opens the file with open64(). It unlocks the fileset * entry lock, sets the DIRECTIO_ON or DIRECTIO_OFF flags * as requested, and returns the file descriptor integer - * for the opened file. + * for the opened file in the supplied filebench file descriptor. + * Returns FILEBENCH_ERROR on error, and FILEBENCH_OK on success. */ int -fileset_openfile(fileset_t *fileset, +fileset_openfile(fb_fdesc_t *fdesc, fileset_t *fileset, filesetentry_t *entry, int flag, int filemode, int attrs) { char path[MAXPATHLEN]; char dir[MAXPATHLEN]; char *pathtmp; struct stat64 sb; - int fd; int open_attrs = 0; (void) fb_strlcpy(path, avd_get_str(fileset->fs_path), MAXPATHLEN); @@ -514,7 +485,8 @@ fileset_openfile(fileset_t *fileset, #endif } - if ((fd = open64(path, flag | open_attrs, filemode)) < 0) { + if (FB_OPEN(fdesc, path, flag | open_attrs, filemode) + == FILEBENCH_ERROR) { filebench_log(LOG_ERROR, "Failed to open file %d, %s, with status %x: %s", entry->fse_index, path, entry->fse_flags, strerror(errno)); @@ -530,12 +502,12 @@ fileset_openfile(fileset_t *fileset, #ifdef sun if (attrs & FLOW_ATTR_DIRECTIO) - (void) directio(fd, DIRECTIO_ON); + (void) directio(fdesc->fd_num, DIRECTIO_ON); else - (void) directio(fd, DIRECTIO_OFF); + (void) directio(fdesc->fd_num, DIRECTIO_OFF); #endif - return (fd); + return (FILEBENCH_OK); } /* @@ -1071,7 +1043,7 @@ fileset_create(fileset_t *fileset) filebench_log(LOG_VERBOSE, "making tree for filset %s", path); - (void) mkdir(path, 0755); + (void) FB_MKDIR(path, 0755); if (fileset_create_subdirs(fileset, path) == FILEBENCH_ERROR) return (FILEBENCH_ERROR); @@ -1120,7 +1092,7 @@ fileset_create(fileset_t *fileset) &filebench_shm->shm_fsparalloc_lock); } - /* quit if any allocation thread reports and error */ + /* quit if any allocation thread reports an error */ if (filebench_shm->shm_fsparalloc_count < 0) { (void) pthread_mutex_unlock( &filebench_shm->shm_fsparalloc_lock); diff --git a/usr/src/cmd/filebench/common/fileset.h b/usr/src/cmd/filebench/common/fileset.h index 1250d50c32..80537d174a 100644 --- a/usr/src/cmd/filebench/common/fileset.h +++ b/usr/src/cmd/filebench/common/fileset.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -50,6 +50,7 @@ #include "vars.h" #include "fb_avl.h" + #define FILE_ALLOC_BLOCK (off64_t)(1024 * 1024) #ifdef __cplusplus @@ -173,8 +174,8 @@ typedef struct fileset { } fileset_t; int fileset_createset(fileset_t *); -int fileset_openfile(fileset_t *fileset, filesetentry_t *entry, - int flag, int mode, int attrs); +int fileset_openfile(fb_fdesc_t *fd, fileset_t *fileset, + filesetentry_t *entry, int flag, int mode, int attrs); fileset_t *fileset_define(avd_t); fileset_t *fileset_find(char *name); filesetentry_t *fileset_pick(fileset_t *fileset, int flags, int tid, diff --git a/usr/src/cmd/filebench/common/flowop.c b/usr/src/cmd/filebench/common/flowop.c index 6a7773b795..a6b3617e2b 100644 --- a/usr/src/cmd/filebench/common/flowop.c +++ b/usr/src/cmd/filebench/common/flowop.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -584,14 +584,44 @@ flowop_start(threadflow_t *threadflow) pthread_exit(&threadflow->tf_abort); } +void flowoplib_flowinit(void); +void fb_lfs_flowinit(void); + void flowop_init(void) { (void) pthread_mutex_init(&controlstats_lock, ipc_mutexattr(IPC_MUTEX_NORMAL)); - flowoplib_init(); + flowoplib_flowinit(); +} + +static int plugin_flowinit_done = FALSE; + +/* + * Initialize any "plug-in" flowops. Called when the first "create fileset" + * command is encountered. + */ +void +flowop_plugin_flowinit(void) +{ + if (plugin_flowinit_done) + return; + + plugin_flowinit_done = TRUE; + + switch (filebench_shm->shm_filesys_type) { + case LOCAL_FS_PLUG: + fb_lfs_flowinit(); + break; + + case NFS3_PLUG: + case NFS4_PLUG: + case CIFS_PLUG: + break; + } } + /* * Delete the designated flowop from the thread's flowop list. */ @@ -1113,3 +1143,62 @@ flowop_composite_destruct(flowop_t *flowop) inner_flowop = inner_flowop->fo_exec_next; } } + +/* + * Support routines for libraries of flowops + */ + +int +flowop_init_generic(flowop_t *flowop) +{ + (void) ipc_mutex_unlock(&flowop->fo_lock); + return (FILEBENCH_OK); +} + +void +flowop_destruct_generic(flowop_t *flowop) +{ + char *buf; + + /* release any local resources held by the flowop */ + (void) ipc_mutex_lock(&flowop->fo_lock); + buf = flowop->fo_buf; + flowop->fo_buf = NULL; + (void) ipc_mutex_unlock(&flowop->fo_lock); + + if (buf) + free(buf); +} + + +/* + * Loops through the supplied list of flowops and creates and initializes + * a flowop for each one by calling flowop_define. As a side effect of + * calling flowop define, the created flowops are placed on the + * master flowop list. All created flowops are set to instance "0". + */ +void +flowop_flow_init(flowop_proto_t *list, int nops) +{ + int i; + + for (i = 0; i < nops; i++) { + flowop_t *flowop; + flowop_proto_t *fl; + + fl = &(list[i]); + + if ((flowop = flowop_define(NULL, + fl->fl_name, NULL, NULL, 0, fl->fl_type)) == 0) { + filebench_log(LOG_ERROR, + "failed to create flowop %s\n", + fl->fl_name); + filebench_shutdown(1); + } + + flowop->fo_func = fl->fl_func; + flowop->fo_init = fl->fl_init; + flowop->fo_destruct = fl->fl_destruct; + flowop->fo_attrs = fl->fl_attrs; + } +} diff --git a/usr/src/cmd/filebench/common/flowop.h b/usr/src/cmd/filebench/common/flowop.h index 976c3d0505..d08367e7b1 100644 --- a/usr/src/cmd/filebench/common/flowop.h +++ b/usr/src/cmd/filebench/common/flowop.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -44,6 +44,7 @@ #include "vars.h" #include "fileset.h" #include "filebench.h" +#include "fsplug.h" #ifdef __cplusplus extern "C" { @@ -135,17 +136,31 @@ typedef struct flowop { #define FLOW_TYPE_COMPOSITE 4 /* Op is a composite flowop */ #define FLOW_TYPE_OTHER 5 /* Op is a something else */ +typedef struct flowop_proto { + int fl_type; + int fl_attrs; + char *fl_name; + int (*fl_init)(); + int (*fl_func)(); + void (*fl_destruct)(); +} flowop_proto_t; + extern flowstat_t controlstats; extern pthread_mutex_t controlstats_lock; void flowop_init(void); +void flowop_plugin_flowinit(void); flowop_t *flowop_define(threadflow_t *, char *name, flowop_t *inherit, flowop_t **flowoplist_hdp, int instance, int type); flowop_t *flowop_find(char *name); flowop_t *flowop_find_one(char *name, int instance); flowop_t *flowop_find_from_list(char *name, flowop_t *list); +int flowop_init_generic(flowop_t *flowop); +void flowop_destruct_generic(flowop_t *flowop); +void flowop_flow_init(flowop_proto_t *list, int nops); void flowoplib_usage(void); -void flowoplib_init(void); +int flowoplib_iosetup(threadflow_t *threadflow, flowop_t *flowop, + fbint_t *wssp, caddr_t *iobufp, fb_fdesc_t **filedescp, fbint_t iosize); void flowop_delete_all(flowop_t **threadlist); void flowop_endop(threadflow_t *threadflow, flowop_t *flowop, int64_t bytes); void flowop_beginop(threadflow_t *threadflow, flowop_t *flowop); diff --git a/usr/src/cmd/filebench/common/flowop_library.c b/usr/src/cmd/filebench/common/flowop_library.c index b2ad1cf28f..26e5f1a3d5 100644 --- a/usr/src/cmd/filebench/common/flowop_library.c +++ b/usr/src/cmd/filebench/common/flowop_library.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Portions Copyright 2008 Denis Cheng @@ -31,6 +31,7 @@ #ifdef HAVE_SYS_ASYNCH_H #include <sys/asynch.h> #endif +#include <stddef.h> #include <sys/ipc.h> #include <sys/sem.h> #include <sys/errno.h> @@ -44,30 +45,14 @@ #include <utility.h> #endif /* HAVE_UTILITY_H */ -#ifdef HAVE_AIO -#include <aio.h> -#endif /* HAVE_AIO */ - -#ifdef HAVE_LIBAIO_H -#include <libaio.h> -#endif /* HAVE_LIBAIO_H */ - #ifdef HAVE_SYS_ASYNC_H #include <sys/asynch.h> #endif /* HAVE_SYS_ASYNC_H */ -#ifdef HAVE_AIO_H -#include <aio.h> -#endif /* HAVE_AIO_H */ - #ifndef HAVE_UINT_T #define uint_t unsigned int #endif /* HAVE_UINT_T */ -#ifndef HAVE_AIOCB64_T -#define aiocb64 aiocb -#endif /* HAVE_AIOCB64_T */ - #ifndef HAVE_SYSV_SEM #include <semaphore.h> #endif /* HAVE_SYSV_SEM */ @@ -77,6 +62,8 @@ #include "fileset.h" #include "fb_random.h" #include "utils.h" +#include "fsplug.h" + /* * These routines implement the flowops from the f language. Each * flowop has has a name such as "read", and a set of function pointers @@ -100,16 +87,10 @@ * by the "name=" attribute. */ -static int flowoplib_init_generic(flowop_t *flowop); -static void flowoplib_destruct_generic(flowop_t *flowop); static void flowoplib_destruct_noop(flowop_t *flowop); static int flowoplib_fdnum(threadflow_t *threadflow, flowop_t *flowop); static int flowoplib_print(threadflow_t *threadflow, flowop_t *flowop); static int flowoplib_write(threadflow_t *threadflow, flowop_t *flowop); -#ifdef HAVE_AIO -static int flowoplib_aiowrite(threadflow_t *threadflow, flowop_t *flowop); -static int flowoplib_aiowait(threadflow_t *threadflow, flowop_t *flowop); -#endif static int flowoplib_read(threadflow_t *threadflow, flowop_t *flowop); static int flowoplib_block_init(flowop_t *flowop); static int flowoplib_block(threadflow_t *threadflow, flowop_t *flowop); @@ -146,140 +127,84 @@ static int flowoplib_testrandvar(threadflow_t *threadflow, flowop_t *flowop); static int flowoplib_testrandvar_init(flowop_t *flowop); static void flowoplib_testrandvar_destruct(flowop_t *flowop); -typedef struct flowoplib { - int fl_type; - int fl_attrs; - char *fl_name; - int (*fl_init)(); - int (*fl_func)(); - void (*fl_destruct)(); -} flowoplib_t; - -static flowoplib_t flowoplib_funcs[] = { - FLOW_TYPE_IO, FLOW_ATTR_WRITE, "write", flowoplib_init_generic, - flowoplib_write, flowoplib_destruct_generic, - FLOW_TYPE_IO, FLOW_ATTR_READ, "read", flowoplib_init_generic, - flowoplib_read, flowoplib_destruct_generic, -#ifdef HAVE_AIO - FLOW_TYPE_AIO, FLOW_ATTR_WRITE, "aiowrite", flowoplib_init_generic, - flowoplib_aiowrite, flowoplib_destruct_generic, - FLOW_TYPE_AIO, 0, "aiowait", flowoplib_init_generic, - flowoplib_aiowait, flowoplib_destruct_generic, -#endif +static flowop_proto_t flowoplib_funcs[] = { + FLOW_TYPE_IO, FLOW_ATTR_WRITE, "write", flowop_init_generic, + flowoplib_write, flowop_destruct_generic, + FLOW_TYPE_IO, FLOW_ATTR_READ, "read", flowop_init_generic, + flowoplib_read, flowop_destruct_generic, FLOW_TYPE_SYNC, 0, "block", flowoplib_block_init, - flowoplib_block, flowoplib_destruct_generic, - FLOW_TYPE_SYNC, 0, "wakeup", flowoplib_init_generic, - flowoplib_wakeup, flowoplib_destruct_generic, + flowoplib_block, flowop_destruct_generic, + FLOW_TYPE_SYNC, 0, "wakeup", flowop_init_generic, + flowoplib_wakeup, flowop_destruct_generic, FLOW_TYPE_SYNC, 0, "semblock", flowoplib_semblock_init, flowoplib_semblock, flowoplib_semblock_destruct, FLOW_TYPE_SYNC, 0, "sempost", flowoplib_sempost_init, flowoplib_sempost, flowoplib_destruct_noop, - FLOW_TYPE_OTHER, 0, "hog", flowoplib_init_generic, - flowoplib_hog, flowoplib_destruct_generic, - FLOW_TYPE_OTHER, 0, "delay", flowoplib_init_generic, - flowoplib_delay, flowoplib_destruct_generic, - FLOW_TYPE_OTHER, 0, "eventlimit", flowoplib_init_generic, - flowoplib_eventlimit, flowoplib_destruct_generic, - FLOW_TYPE_OTHER, 0, "bwlimit", flowoplib_init_generic, - flowoplib_bwlimit, flowoplib_destruct_generic, - FLOW_TYPE_OTHER, 0, "iopslimit", flowoplib_init_generic, - flowoplib_iopslimit, flowoplib_destruct_generic, - FLOW_TYPE_OTHER, 0, "opslimit", flowoplib_init_generic, - flowoplib_opslimit, flowoplib_destruct_generic, - FLOW_TYPE_OTHER, 0, "finishoncount", flowoplib_init_generic, - flowoplib_finishoncount, flowoplib_destruct_generic, - FLOW_TYPE_OTHER, 0, "finishonbytes", flowoplib_init_generic, - flowoplib_finishonbytes, flowoplib_destruct_generic, - FLOW_TYPE_IO, 0, "openfile", flowoplib_init_generic, - flowoplib_openfile, flowoplib_destruct_generic, - FLOW_TYPE_IO, 0, "createfile", flowoplib_init_generic, - flowoplib_createfile, flowoplib_destruct_generic, - FLOW_TYPE_IO, 0, "closefile", flowoplib_init_generic, - flowoplib_closefile, flowoplib_destruct_generic, - FLOW_TYPE_IO, 0, "makedir", flowoplib_init_generic, - flowoplib_makedir, flowoplib_destruct_generic, - FLOW_TYPE_IO, 0, "removedir", flowoplib_init_generic, - flowoplib_removedir, flowoplib_destruct_generic, - FLOW_TYPE_IO, 0, "listdir", flowoplib_init_generic, - flowoplib_listdir, flowoplib_destruct_generic, - FLOW_TYPE_IO, 0, "fsync", flowoplib_init_generic, - flowoplib_fsync, flowoplib_destruct_generic, - FLOW_TYPE_IO, 0, "fsyncset", flowoplib_init_generic, - flowoplib_fsyncset, flowoplib_destruct_generic, - FLOW_TYPE_IO, 0, "statfile", flowoplib_init_generic, - flowoplib_statfile, flowoplib_destruct_generic, - FLOW_TYPE_IO, FLOW_ATTR_READ, "readwholefile", flowoplib_init_generic, - flowoplib_readwholefile, flowoplib_destruct_generic, - FLOW_TYPE_IO, FLOW_ATTR_WRITE, "appendfile", flowoplib_init_generic, - flowoplib_appendfile, flowoplib_destruct_generic, - FLOW_TYPE_IO, FLOW_ATTR_WRITE, "appendfilerand", flowoplib_init_generic, - flowoplib_appendfilerand, flowoplib_destruct_generic, - FLOW_TYPE_IO, 0, "deletefile", flowoplib_init_generic, - flowoplib_deletefile, flowoplib_destruct_generic, - FLOW_TYPE_IO, FLOW_ATTR_WRITE, "writewholefile", flowoplib_init_generic, - flowoplib_writewholefile, flowoplib_destruct_generic, - FLOW_TYPE_OTHER, 0, "print", flowoplib_init_generic, - flowoplib_print, flowoplib_destruct_generic, + FLOW_TYPE_OTHER, 0, "hog", flowop_init_generic, + flowoplib_hog, flowop_destruct_generic, + FLOW_TYPE_OTHER, 0, "delay", flowop_init_generic, + flowoplib_delay, flowop_destruct_generic, + FLOW_TYPE_OTHER, 0, "eventlimit", flowop_init_generic, + flowoplib_eventlimit, flowop_destruct_generic, + FLOW_TYPE_OTHER, 0, "bwlimit", flowop_init_generic, + flowoplib_bwlimit, flowop_destruct_generic, + FLOW_TYPE_OTHER, 0, "iopslimit", flowop_init_generic, + flowoplib_iopslimit, flowop_destruct_generic, + FLOW_TYPE_OTHER, 0, "opslimit", flowop_init_generic, + flowoplib_opslimit, flowop_destruct_generic, + FLOW_TYPE_OTHER, 0, "finishoncount", flowop_init_generic, + flowoplib_finishoncount, flowop_destruct_generic, + FLOW_TYPE_OTHER, 0, "finishonbytes", flowop_init_generic, + flowoplib_finishonbytes, flowop_destruct_generic, + FLOW_TYPE_IO, 0, "openfile", flowop_init_generic, + flowoplib_openfile, flowop_destruct_generic, + FLOW_TYPE_IO, 0, "createfile", flowop_init_generic, + flowoplib_createfile, flowop_destruct_generic, + FLOW_TYPE_IO, 0, "closefile", flowop_init_generic, + flowoplib_closefile, flowop_destruct_generic, + FLOW_TYPE_IO, 0, "makedir", flowop_init_generic, + flowoplib_makedir, flowop_destruct_generic, + FLOW_TYPE_IO, 0, "removedir", flowop_init_generic, + flowoplib_removedir, flowop_destruct_generic, + FLOW_TYPE_IO, 0, "listdir", flowop_init_generic, + flowoplib_listdir, flowop_destruct_generic, + FLOW_TYPE_IO, 0, "fsync", flowop_init_generic, + flowoplib_fsync, flowop_destruct_generic, + FLOW_TYPE_IO, 0, "fsyncset", flowop_init_generic, + flowoplib_fsyncset, flowop_destruct_generic, + FLOW_TYPE_IO, 0, "statfile", flowop_init_generic, + flowoplib_statfile, flowop_destruct_generic, + FLOW_TYPE_IO, FLOW_ATTR_READ, "readwholefile", flowop_init_generic, + flowoplib_readwholefile, flowop_destruct_generic, + FLOW_TYPE_IO, FLOW_ATTR_WRITE, "appendfile", flowop_init_generic, + flowoplib_appendfile, flowop_destruct_generic, + FLOW_TYPE_IO, FLOW_ATTR_WRITE, "appendfilerand", flowop_init_generic, + flowoplib_appendfilerand, flowop_destruct_generic, + FLOW_TYPE_IO, 0, "deletefile", flowop_init_generic, + flowoplib_deletefile, flowop_destruct_generic, + FLOW_TYPE_IO, FLOW_ATTR_WRITE, "writewholefile", flowop_init_generic, + flowoplib_writewholefile, flowop_destruct_generic, + FLOW_TYPE_OTHER, 0, "print", flowop_init_generic, + flowoplib_print, flowop_destruct_generic, /* routine to calculate mean and stddev for output from a randvar */ FLOW_TYPE_OTHER, 0, "testrandvar", flowoplib_testrandvar_init, flowoplib_testrandvar, flowoplib_testrandvar_destruct }; /* - * Loops through the master list of flowops defined in this + * Loops through the list of flowops defined in this * module, and creates and initializes a flowop for each one - * by calling flowop_define. As a side effect of calling - * flowop define, the created flowops are placed on the + * by calling flowop_flow_init. As a side effect of calling + * flowop_flow_init, the created flowops are placed on the * master flowop list. All created flowops are set to * instance "0". */ void -flowoplib_init() +flowoplib_flowinit() { - int nops = sizeof (flowoplib_funcs) / sizeof (flowoplib_t); - int i; - - for (i = 0; i < nops; i++) { - flowop_t *flowop; - flowoplib_t *fl; + int nops = sizeof (flowoplib_funcs) / sizeof (flowop_proto_t); - fl = &flowoplib_funcs[i]; - - if ((flowop = flowop_define(NULL, - fl->fl_name, NULL, NULL, 0, fl->fl_type)) == 0) { - filebench_log(LOG_ERROR, - "failed to create flowop %s\n", - fl->fl_name); - filebench_shutdown(1); - } - - flowop->fo_func = fl->fl_func; - flowop->fo_init = fl->fl_init; - flowop->fo_destruct = fl->fl_destruct; - flowop->fo_attrs = fl->fl_attrs; - } -} - -static int -flowoplib_init_generic(flowop_t *flowop) -{ - (void) ipc_mutex_unlock(&flowop->fo_lock); - return (FILEBENCH_OK); -} - -static void -flowoplib_destruct_generic(flowop_t *flowop) -{ - char *buf; - - /* release any local resources held by the flowop */ - (void) ipc_mutex_lock(&flowop->fo_lock); - buf = flowop->fo_buf; - flowop->fo_buf = NULL; - (void) ipc_mutex_unlock(&flowop->fo_lock); - - if (buf) - free(buf); + flowop_flow_init(flowoplib_funcs, nops); } /* @@ -461,14 +386,14 @@ flowoplib_fdnum(threadflow_t *threadflow, flowop_t *flowop) */ static int flowoplib_filesetup(threadflow_t *threadflow, flowop_t *flowop, - fbint_t *wssp, int *filedescp) + fbint_t *wssp, fb_fdesc_t **fdescp) { int fd = flowoplib_fdnum(threadflow, flowop); if (fd == -1) return (FILEBENCH_ERROR); - if (threadflow->tf_fd[fd] == 0) { + if (threadflow->tf_fd[fd].fd_ptr == NULL) { int ret; if ((ret = flowoplib_openfile_common( @@ -486,7 +411,7 @@ flowoplib_filesetup(threadflow_t *threadflow, flowop_t *flowop, } } - *filedescp = threadflow->tf_fd[fd]; + *fdescp = &(threadflow->tf_fd[fd]); if ((*wssp = flowop->fo_constwss) == 0) { if (threadflow->tf_fse[fd]) @@ -556,9 +481,9 @@ flowoplib_iobufsetup(threadflow_t *threadflow, flowop_t *flowop, * io buffer or random offset into tf_mem for IO operation and the wss * value. Returns FILEBENCH_ERROR on errors, FILEBENCH_OK otherwise. */ -static int +int flowoplib_iosetup(threadflow_t *threadflow, flowop_t *flowop, - fbint_t *wssp, caddr_t *iobufp, int *filedescp, fbint_t iosize) + fbint_t *wssp, caddr_t *iobufp, fb_fdesc_t **filedescp, fbint_t iosize) { int ret; @@ -595,13 +520,13 @@ flowoplib_read(threadflow_t *threadflow, flowop_t *flowop) caddr_t iobuf; fbint_t wss; fbint_t iosize; - int filedesc; + fb_fdesc_t *fdesc; int ret; iosize = avd_get_int(flowop->fo_iosize); if ((ret = flowoplib_iosetup(threadflow, flowop, &wss, &iobuf, - &filedesc, iosize)) != FILEBENCH_OK) + &fdesc, iosize)) != FILEBENCH_OK) return (ret); if (avd_get_bool(flowop->fo_random)) { @@ -616,7 +541,7 @@ flowoplib_read(threadflow_t *threadflow, flowop_t *flowop) } (void) flowop_beginop(threadflow, flowop); - if ((ret = pread64(filedesc, iobuf, + if ((ret = FB_PREAD(fdesc, iobuf, iosize, (off64_t)fileoffset)) == -1) { (void) flowop_endop(threadflow, flowop, 0); filebench_log(LOG_ERROR, @@ -630,11 +555,11 @@ flowoplib_read(threadflow_t *threadflow, flowop_t *flowop) (void) flowop_endop(threadflow, flowop, ret); if ((ret == 0)) - (void) lseek64(filedesc, 0, SEEK_SET); + (void) FB_LSEEK(fdesc, 0, SEEK_SET); } else { (void) flowop_beginop(threadflow, flowop); - if ((ret = read(filedesc, iobuf, iosize)) == -1) { + if ((ret = FB_READ(fdesc, iobuf, iosize)) == -1) { (void) flowop_endop(threadflow, flowop, 0); filebench_log(LOG_ERROR, "read file %s failed, io buffer %zd: %s", @@ -646,281 +571,12 @@ flowoplib_read(threadflow_t *threadflow, flowop_t *flowop) (void) flowop_endop(threadflow, flowop, ret); if ((ret == 0)) - (void) lseek64(filedesc, 0, SEEK_SET); - } - - return (FILEBENCH_OK); -} - -#ifdef HAVE_AIO - -/* - * Asynchronous write section. An Asynchronous IO element - * (aiolist_t) is used to associate the asynchronous write request with - * its subsequent completion. This element includes a aiocb64 struct - * that is used by posix aio_xxx calls to track the asynchronous writes. - * The flowops aiowrite and aiowait result in calls to these posix - * aio_xxx system routines to do the actual asynchronous write IO - * operations. - */ - - -/* - * Allocates an asynchronous I/O list (aio, of type - * aiolist_t) element. Adds it to the flowop thread's - * threadflow aio list. Returns a pointer to the element. - */ -static aiolist_t * -aio_allocate(flowop_t *flowop) -{ - aiolist_t *aiolist; - - if ((aiolist = malloc(sizeof (aiolist_t))) == NULL) { - filebench_log(LOG_ERROR, "malloc aiolist failed"); - filebench_shutdown(1); - } - - /* Add to list */ - if (flowop->fo_thread->tf_aiolist == NULL) { - flowop->fo_thread->tf_aiolist = aiolist; - aiolist->al_next = NULL; - } else { - aiolist->al_next = flowop->fo_thread->tf_aiolist; - flowop->fo_thread->tf_aiolist = aiolist; - } - return (aiolist); -} - -/* - * Searches for the aiolist element that has a matching - * completion block, aiocb. If none found returns FILEBENCH_ERROR. If - * found, removes the aiolist element from flowop thread's - * list and returns FILEBENCH_OK. - */ -static int -aio_deallocate(flowop_t *flowop, struct aiocb64 *aiocb) -{ - aiolist_t *aiolist = flowop->fo_thread->tf_aiolist; - aiolist_t *previous = NULL; - aiolist_t *match = NULL; - - if (aiocb == NULL) { - filebench_log(LOG_ERROR, "null aiocb deallocate"); - return (FILEBENCH_OK); - } - - while (aiolist) { - if (aiocb == &(aiolist->al_aiocb)) { - match = aiolist; - break; - } - previous = aiolist; - aiolist = aiolist->al_next; - } - - if (match == NULL) - return (FILEBENCH_ERROR); - - /* Remove from the list */ - if (previous) - previous->al_next = match->al_next; - else - flowop->fo_thread->tf_aiolist = match->al_next; - - return (FILEBENCH_OK); -} - -/* - * Emulate posix aiowrite(). Determines which file to use, - * either one file of a fileset, or the file associated - * with a fileobj, allocates and fills an aiolist_t element - * for the write, and issues the asynchronous write. This - * operation is only valid for random IO, and returns an - * error if the flowop is set for sequential IO. Returns - * FILEBENCH_OK on success, FILEBENCH_NORSC if iosetup can't - * obtain a file to open, and FILEBENCH_ERROR on any - * encountered error. - */ -static int -flowoplib_aiowrite(threadflow_t *threadflow, flowop_t *flowop) -{ - caddr_t iobuf; - fbint_t wss; - fbint_t iosize; - int filedesc; - int ret; - - iosize = avd_get_int(flowop->fo_iosize); - - if ((ret = flowoplib_iosetup(threadflow, flowop, &wss, &iobuf, - &filedesc, iosize)) != FILEBENCH_OK) - return (ret); - - if (avd_get_bool(flowop->fo_random)) { - uint64_t fileoffset; - struct aiocb64 *aiocb; - aiolist_t *aiolist; - - if (filebench_randomno64(&fileoffset, - wss, iosize, NULL) == -1) { - filebench_log(LOG_ERROR, - "file size smaller than IO size for thread %s", - flowop->fo_name); - return (FILEBENCH_ERROR); - } - - aiolist = aio_allocate(flowop); - aiolist->al_type = AL_WRITE; - aiocb = &aiolist->al_aiocb; - - aiocb->aio_fildes = filedesc; - aiocb->aio_buf = iobuf; - aiocb->aio_nbytes = (size_t)iosize; - aiocb->aio_offset = (off64_t)fileoffset; - aiocb->aio_reqprio = 0; - - filebench_log(LOG_DEBUG_IMPL, - "aio fd=%d, bytes=%llu, offset=%llu", - filedesc, (u_longlong_t)iosize, (u_longlong_t)fileoffset); - - flowop_beginop(threadflow, flowop); - if (aio_write64(aiocb) < 0) { - filebench_log(LOG_ERROR, "aiowrite failed: %s", - strerror(errno)); - filebench_shutdown(1); - } - flowop_endop(threadflow, flowop, iosize); - } else { - return (FILEBENCH_ERROR); - } - - return (FILEBENCH_OK); -} - - - -#define MAXREAP 4096 - -/* - * Emulate posix aiowait(). Waits for the completion of half the - * outstanding asynchronous IOs, or a single IO, which ever is - * larger. The routine will return after a sufficient number of - * completed calls issued by any thread in the procflow have - * completed, or a 1 second timout elapses. All completed - * IO operations are deleted from the thread's aiolist. - */ -static int -flowoplib_aiowait(threadflow_t *threadflow, flowop_t *flowop) -{ - struct aiocb64 **worklist; - aiolist_t *aio = flowop->fo_thread->tf_aiolist; - int uncompleted = 0; - - worklist = calloc(MAXREAP, sizeof (struct aiocb64 *)); - - /* Count the list of pending aios */ - while (aio) { - uncompleted++; - aio = aio->al_next; + (void) FB_LSEEK(fdesc, 0, SEEK_SET); } - do { - uint_t ncompleted = 0; - uint_t todo; - struct timespec timeout; - int inprogress; - int i; - - /* Wait for half of the outstanding requests */ - timeout.tv_sec = 1; - timeout.tv_nsec = 0; - - if (uncompleted > MAXREAP) - todo = MAXREAP; - else - todo = uncompleted / 2; - - if (todo == 0) - todo = 1; - - flowop_beginop(threadflow, flowop); - -#ifdef HAVE_AIOWAITN - if ((aio_waitn64((struct aiocb64 **)worklist, - MAXREAP, &todo, &timeout) == -1) && - errno && (errno != ETIME)) { - filebench_log(LOG_ERROR, - "aiowait failed: %s, outstanding = %d, " - "ncompleted = %d ", - strerror(errno), uncompleted, todo); - } - - ncompleted = todo; - /* Take the completed I/Os from the list */ - inprogress = 0; - for (i = 0; i < ncompleted; i++) { - if ((aio_return64(worklist[i]) == -1) && - (errno == EINPROGRESS)) { - inprogress++; - continue; - } - if (aio_deallocate(flowop, worklist[i]) < 0) { - filebench_log(LOG_ERROR, "Could not remove " - "aio from list "); - flowop_endop(threadflow, flowop, 0); - return (FILEBENCH_ERROR); - } - } - - uncompleted -= ncompleted; - uncompleted += inprogress; - -#else - - for (ncompleted = 0, inprogress = 0, - aio = flowop->fo_thread->tf_aiolist; - ncompleted < todo, aio != NULL; aio = aio->al_next) { - int result = aio_error64(&aio->al_aiocb); - - if (result == EINPROGRESS) { - inprogress++; - continue; - } - - if ((aio_return64(&aio->al_aiocb) == -1) || result) { - filebench_log(LOG_ERROR, "aio failed: %s", - strerror(result)); - continue; - } - - ncompleted++; - - if (aio_deallocate(flowop, &aio->al_aiocb) < 0) { - filebench_log(LOG_ERROR, "Could not remove aio " - "from list "); - flowop_endop(threadflow, flowop, 0); - return (FILEBENCH_ERROR); - } - } - - uncompleted -= ncompleted; - -#endif - filebench_log(LOG_DEBUG_SCRIPT, - "aio2 completed %d ios, uncompleted = %d, inprogress = %d", - ncompleted, uncompleted, inprogress); - - } while (uncompleted > MAXREAP); - - flowop_endop(threadflow, flowop, 0); - - free(worklist); - return (FILEBENCH_OK); } -#endif /* HAVE_AIO */ - /* * Initializes a "flowop_block" flowop. Specifically, it * initializes the flowop's fo_cv and unlocks the fo_lock. @@ -1791,11 +1447,6 @@ flowoplib_sempost(threadflow_t *threadflow, flowop_t *flowop) */ /* - * XXX Making file selection more consistent among the flowops might good - */ - - -/* * Emulates (and actually does) file open. Obtains a file descriptor * index, then calls flowoplib_openfile_common() to open. Returns * FILEBENCH_ERROR if no file descriptor is found, and returns the @@ -1852,7 +1503,7 @@ flowoplib_openfile_common(threadflow_t *threadflow, flowop_t *flowop, int fd) if (avd_get_bool(flowop->fo_rotatefd)) tid = threadflow->tf_utid; - if (threadflow->tf_fd[fd] != 0) { + if (threadflow->tf_fd[fd].fd_ptr != NULL) { filebench_log(LOG_ERROR, "flowop %s attempted to open without closing on fd %d", flowop->fo_name, fd); @@ -1880,10 +1531,8 @@ flowoplib_openfile_common(threadflow_t *threadflow, flowop_t *flowop, int fd) filebench_log(LOG_DEBUG_SCRIPT, "open raw device %s flags %d = %d", name, open_attrs, fd); - threadflow->tf_fd[fd] = open64(name, - O_RDWR | open_attrs, 0666); - - if (threadflow->tf_fd[fd] < 0) { + if (FB_OPEN(&(threadflow->tf_fd[fd]), name, + O_RDWR | open_attrs, 0666) == FILEBENCH_ERROR) { filebench_log(LOG_ERROR, "Failed to open raw device %s: %s", name, strerror(errno)); @@ -1892,7 +1541,7 @@ flowoplib_openfile_common(threadflow_t *threadflow, flowop_t *flowop, int fd) /* if running on Solaris, use un-buffered io */ #ifdef sun - (void) directio(threadflow->tf_fd[fd], DIRECTIO_ON); + (void) directio(threadflow->tf_fd[fd].fd_num, DIRECTIO_ON); #endif threadflow->tf_fse[fd] = NULL; @@ -1912,11 +1561,11 @@ flowoplib_openfile_common(threadflow_t *threadflow, flowop_t *flowop, int fd) threadflow->tf_fse[fd] = file; flowop_beginop(threadflow, flowop); - threadflow->tf_fd[fd] = fileset_openfile(flowop->fo_fileset, + err = fileset_openfile(&threadflow->tf_fd[fd], flowop->fo_fileset, file, O_RDWR, 0666, flowoplib_fileattrs(flowop)); flowop_endop(threadflow, flowop, 0); - if (threadflow->tf_fd[fd] < 0) { + if (err == FILEBENCH_ERROR) { filebench_log(LOG_ERROR, "flowop %s failed to open file %s", flowop->fo_name, file->fse_path); return (FILEBENCH_ERROR); @@ -1948,7 +1597,7 @@ flowoplib_createfile(threadflow_t *threadflow, flowop_t *flowop) int fd = flowop->fo_fdnumber; int err; - if (threadflow->tf_fd[fd] != 0) { + if (threadflow->tf_fd[fd].fd_ptr != NULL) { filebench_log(LOG_ERROR, "flowop %s attempted to create without closing on fd %d", flowop->fo_name, fd); @@ -1982,11 +1631,11 @@ flowoplib_createfile(threadflow_t *threadflow, flowop_t *flowop) threadflow->tf_fse[fd] = file; flowop_beginop(threadflow, flowop); - threadflow->tf_fd[fd] = fileset_openfile(flowop->fo_fileset, + err = fileset_openfile(&threadflow->tf_fd[fd], flowop->fo_fileset, file, O_RDWR | O_CREAT, 0666, flowoplib_fileattrs(flowop)); flowop_endop(threadflow, flowop, 0); - if (threadflow->tf_fd[fd] < 0) { + if (err == FILEBENCH_ERROR) { filebench_log(LOG_ERROR, "failed to create file %s", flowop->fo_name); return (FILEBENCH_ERROR); @@ -2074,7 +1723,7 @@ flowoplib_deletefile(threadflow_t *threadflow, flowop_t *flowop) } /* don't delete if anyone (other than me) has file open */ - if ((fd > 0) && (threadflow->tf_fd[fd] > 0)) { + if ((fd > 0) && (threadflow->tf_fd[fd].fd_num > 0)) { if (file->fse_open_cnt > 1) { filebench_log(LOG_DEBUG_SCRIPT, "flowop %s can't delete file opened by other" @@ -2104,7 +1753,7 @@ flowoplib_deletefile(threadflow_t *threadflow, flowop_t *flowop) /* delete the selected file */ flowop_beginop(threadflow, flowop); - (void) unlink(path); + (void) FB_UNLINK(path); flowop_endop(threadflow, flowop, 0); /* indicate that it is no longer busy and no longer exists */ @@ -2128,7 +1777,7 @@ flowoplib_fsync(threadflow_t *threadflow, flowop_t *flowop) filesetentry_t *file; int fd = flowop->fo_fdnumber; - if (threadflow->tf_fd[fd] == 0) { + if (threadflow->tf_fd[fd].fd_ptr == NULL) { filebench_log(LOG_ERROR, "flowop %s attempted to fsync a closed fd %d", flowop->fo_name, fd); @@ -2147,7 +1796,7 @@ flowoplib_fsync(threadflow_t *threadflow, flowop_t *flowop) /* Measure time to fsync */ flowop_beginop(threadflow, flowop); - (void) fsync(threadflow->tf_fd[fd]); + (void) FB_FSYNC(&threadflow->tf_fd[fd]); flowop_endop(threadflow, flowop, 0); filebench_log(LOG_DEBUG_SCRIPT, "fsync file %s", file->fse_path); @@ -2176,7 +1825,7 @@ flowoplib_fsyncset(threadflow_t *threadflow, flowop_t *flowop) /* Measure time to fsync */ flowop_beginop(threadflow, flowop); - (void) fsync(threadflow->tf_fd[fd]); + (void) FB_FSYNC(&threadflow->tf_fd[fd]); flowop_endop(threadflow, flowop, 0); file = threadflow->tf_fse[fd]; @@ -2204,7 +1853,7 @@ flowoplib_closefile(threadflow_t *threadflow, flowop_t *flowop) fileset_t *fileset; int fd = flowop->fo_fdnumber; - if (threadflow->tf_fd[fd] == 0) { + if (threadflow->tf_fd[fd].fd_ptr == NULL) { filebench_log(LOG_ERROR, "flowop %s attempted to close an already closed fd %d", flowop->fo_name, fd); @@ -2233,12 +1882,12 @@ flowoplib_closefile(threadflow_t *threadflow, flowop_t *flowop) /* Measure time to close */ flowop_beginop(threadflow, flowop); - (void) close(threadflow->tf_fd[fd]); + (void) FB_CLOSE(&threadflow->tf_fd[fd]); flowop_endop(threadflow, flowop, 0); fileset_unbusy(file, FALSE, FALSE, -1); - threadflow->tf_fd[fd] = 0; + threadflow->tf_fd[fd].fd_ptr = NULL; filebench_log(LOG_DEBUG_SCRIPT, "closed file %s", file->fse_path); @@ -2303,7 +1952,7 @@ flowoplib_makedir(threadflow_t *threadflow, flowop_t *flowop) return (ret); flowop_beginop(threadflow, flowop); - (void) mkdir(full_path, 0755); + (void) FB_MKDIR(full_path, 0755); flowop_endop(threadflow, flowop, 0); /* indicate that it is no longer busy and now exists */ @@ -2335,7 +1984,7 @@ flowoplib_removedir(threadflow_t *threadflow, flowop_t *flowop) return (ret); flowop_beginop(threadflow, flowop); - (void) rmdir(full_path); + (void) FB_RMDIR(full_path); flowop_endop(threadflow, flowop, 0); /* indicate that it is no longer busy and no longer exists */ @@ -2360,7 +2009,7 @@ flowoplib_listdir(threadflow_t *threadflow, flowop_t *flowop) { fileset_t *fileset; filesetentry_t *dir; - DIR *dir_handlep; + DIR *dir_handle; struct dirent *direntp; int dir_bytes = 0; int ret; @@ -2385,7 +2034,7 @@ flowoplib_listdir(threadflow_t *threadflow, flowop_t *flowop) flowop_beginop(threadflow, flowop); /* open the directory */ - if ((dir_handlep = opendir(full_path)) == NULL) { + if ((dir_handle = FB_OPENDIR(full_path)) == NULL) { filebench_log(LOG_ERROR, "flowop %s failed to open directory in fileset %s\n", flowop->fo_name, avd_get_str(fileset->fs_name)); @@ -2393,13 +2042,13 @@ flowoplib_listdir(threadflow_t *threadflow, flowop_t *flowop) } /* read through the directory entries */ - while ((direntp = readdir(dir_handlep)) != NULL) { + while ((direntp = FB_READDIR(dir_handle)) != NULL) { dir_bytes += (strlen(direntp->d_name) + sizeof (struct dirent) - 1); } /* close the directory */ - (void) closedir(dir_handlep); + (void) FB_CLOSEDIR(dir_handle); flowop_endop(threadflow, flowop, dir_bytes); @@ -2421,11 +2070,11 @@ flowoplib_statfile(threadflow_t *threadflow, flowop_t *flowop) { filesetentry_t *file; fileset_t *fileset; - struct stat statbuf; + struct stat64 statbuf; int fd = flowop->fo_fdnumber; /* if fd specified and the file is open, use it to access file */ - if ((fd > 0) && ((threadflow->tf_fd[fd]) > 0)) { + if ((fd > 0) && (threadflow->tf_fd[fd].fd_num > 0)) { /* check whether file handle still valid */ if ((file = threadflow->tf_fse[fd]) == NULL) { @@ -2485,7 +2134,7 @@ flowoplib_statfile(threadflow_t *threadflow, flowop_t *flowop) /* stat the file */ flowop_beginop(threadflow, flowop); - if (stat(path, &statbuf) == -1) + if (FB_STAT(path, &statbuf) == -1) filebench_log(LOG_ERROR, "statfile flowop %s failed", flowop->fo_name); flowop_endop(threadflow, flowop, 0); @@ -2494,7 +2143,7 @@ flowoplib_statfile(threadflow_t *threadflow, flowop_t *flowop) } else { /* stat specific file */ flowop_beginop(threadflow, flowop); - if (fstat(threadflow->tf_fd[fd], &statbuf) == -1) + if (FB_FSTAT(&threadflow->tf_fd[fd], &statbuf) == -1) filebench_log(LOG_ERROR, "statfile flowop %s failed", flowop->fo_name); flowop_endop(threadflow, flowop, 0); @@ -2528,7 +2177,7 @@ flowoplib_readwholefile(threadflow_t *threadflow, flowop_t *flowop) { caddr_t iobuf; off64_t bytes = 0; - int filedesc; + fb_fdesc_t *fdesc; uint64_t wss; fbint_t iosize; int ret; @@ -2536,7 +2185,7 @@ flowoplib_readwholefile(threadflow_t *threadflow, flowop_t *flowop) /* get the file to use */ if ((ret = flowoplib_filesetup(threadflow, flowop, &wss, - &filedesc)) != FILEBENCH_OK) + &fdesc)) != FILEBENCH_OK) return (ret); /* an I/O size of zero means read entire working set with one I/O */ @@ -2560,8 +2209,8 @@ flowoplib_readwholefile(threadflow_t *threadflow, flowop_t *flowop) /* Measure time to read bytes */ flowop_beginop(threadflow, flowop); - (void) lseek64(filedesc, 0, SEEK_SET); - while ((ret = read(filedesc, iobuf, iosize)) > 0) + (void) FB_LSEEK(fdesc, 0, SEEK_SET); + while ((ret = FB_READ(fdesc, iobuf, iosize)) > 0) bytes += ret; flowop_endop(threadflow, flowop, bytes); @@ -2597,12 +2246,12 @@ flowoplib_write(threadflow_t *threadflow, flowop_t *flowop) caddr_t iobuf; fbint_t wss; fbint_t iosize; - int filedesc; + fb_fdesc_t *fdesc; int ret; iosize = avd_get_int(flowop->fo_iosize); if ((ret = flowoplib_iosetup(threadflow, flowop, &wss, &iobuf, - &filedesc, iosize)) != FILEBENCH_OK) + &fdesc, iosize)) != FILEBENCH_OK) return (ret); if (avd_get_bool(flowop->fo_random)) { @@ -2616,7 +2265,7 @@ flowoplib_write(threadflow_t *threadflow, flowop_t *flowop) return (FILEBENCH_ERROR); } flowop_beginop(threadflow, flowop); - if (pwrite64(filedesc, iobuf, + if (FB_PWRITE(fdesc, iobuf, iosize, (off64_t)fileoffset) == -1) { filebench_log(LOG_ERROR, "write failed, " "offset %llu io buffer %zd: %s", @@ -2627,7 +2276,7 @@ flowoplib_write(threadflow_t *threadflow, flowop_t *flowop) flowop_endop(threadflow, flowop, iosize); } else { flowop_beginop(threadflow, flowop); - if (write(filedesc, iobuf, iosize) == -1) { + if (FB_WRITE(fdesc, iobuf, iosize) == -1) { filebench_log(LOG_ERROR, "write failed, io buffer %zd: %s", iobuf, strerror(errno)); @@ -2658,14 +2307,14 @@ flowoplib_writewholefile(threadflow_t *threadflow, flowop_t *flowop) off64_t bytes = 0; uint64_t wss; fbint_t iosize; - int filedesc; + fb_fdesc_t *fdesc; int srcfd = flowop->fo_srcfdnumber; int ret; char zerowrtbuf; /* get the file to use */ if ((ret = flowoplib_filesetup(threadflow, flowop, &wss, - &filedesc)) != FILEBENCH_OK) + &fdesc)) != FILEBENCH_OK) return (ret); /* an I/O size of zero means write entire working set with one I/O */ @@ -2702,11 +2351,11 @@ flowoplib_writewholefile(threadflow_t *threadflow, flowop_t *flowop) /* Measure time to write bytes */ flowop_beginop(threadflow, flowop); for (seek = 0; seek < wss; seek += wsize) { - ret = write(filedesc, iobuf, wsize); + ret = FB_WRITE(fdesc, iobuf, wsize); if (ret != wsize) { filebench_log(LOG_ERROR, "Failed to write %d bytes on fd %d: %s", - wsize, filedesc, strerror(errno)); + wsize, fdesc->fd_num, strerror(errno)); flowop_endop(threadflow, flowop, 0); return (FILEBENCH_ERROR); } @@ -2739,26 +2388,26 @@ static int flowoplib_appendfile(threadflow_t *threadflow, flowop_t *flowop) { caddr_t iobuf; - int filedesc; + fb_fdesc_t *fdesc; fbint_t wss; fbint_t iosize; int ret; iosize = avd_get_int(flowop->fo_iosize); if ((ret = flowoplib_iosetup(threadflow, flowop, &wss, &iobuf, - &filedesc, iosize)) != FILEBENCH_OK) + &fdesc, iosize)) != FILEBENCH_OK) return (ret); /* XXX wss is not being used */ /* Measure time to write bytes */ flowop_beginop(threadflow, flowop); - (void) lseek64(filedesc, 0, SEEK_END); - ret = write(filedesc, iobuf, iosize); + (void) FB_LSEEK(fdesc, 0, SEEK_END); + ret = FB_WRITE(fdesc, iobuf, iosize); if (ret != iosize) { filebench_log(LOG_ERROR, "Failed to write %llu bytes on fd %d: %s", - (u_longlong_t)iosize, filedesc, strerror(errno)); + (u_longlong_t)iosize, fdesc->fd_num, strerror(errno)); flowop_endop(threadflow, flowop, ret); return (FILEBENCH_ERROR); } @@ -2788,7 +2437,7 @@ flowoplib_appendfilerand(threadflow_t *threadflow, flowop_t *flowop) { caddr_t iobuf; uint64_t appendsize; - int filedesc; + fb_fdesc_t *fdesc; fbint_t wss; fbint_t iosize; int ret = 0; @@ -2810,7 +2459,7 @@ flowoplib_appendfilerand(threadflow_t *threadflow, flowop_t *flowop) } if ((ret = flowoplib_iosetup(threadflow, flowop, &wss, &iobuf, - &filedesc, appendsize)) != FILEBENCH_OK) + &fdesc, appendsize)) != FILEBENCH_OK) return (ret); /* XXX wss is not being used */ @@ -2818,12 +2467,12 @@ flowoplib_appendfilerand(threadflow_t *threadflow, flowop_t *flowop) /* Measure time to write bytes */ flowop_beginop(threadflow, flowop); - (void) lseek64(filedesc, 0, SEEK_END); - ret = write(filedesc, iobuf, appendsize); + (void) FB_LSEEK(fdesc, 0, SEEK_END); + ret = FB_WRITE(fdesc, iobuf, appendsize); if (ret != appendsize) { filebench_log(LOG_ERROR, "Failed to write %llu bytes on fd %d: %s", - (u_longlong_t)appendsize, filedesc, strerror(errno)); + (u_longlong_t)appendsize, fdesc->fd_num, strerror(errno)); flowop_endop(threadflow, flowop, 0); return (FILEBENCH_ERROR); } diff --git a/usr/src/cmd/filebench/common/fsplug.h b/usr/src/cmd/filebench/common/fsplug.h new file mode 100644 index 0000000000..4158f9f33a --- /dev/null +++ b/usr/src/cmd/filebench/common/fsplug.h @@ -0,0 +1,144 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + * + */ + + +#ifndef _FSPLUG_H +#define _FSPLUG_H + +#include <dirent.h> +#include "config.h" +#include <sys/stat.h> + +/* + * Type of file system client plug-in desired. + */ +typedef enum fb_plugin_type { + LOCAL_FS_PLUG = 0, + NFS3_PLUG, + NFS4_PLUG, + CIFS_PLUG +} fb_plugin_type_t; + +/* universal file descriptor for both local and nfs file systems */ +typedef union fb_fdesc { + int fd_num; /* OS file descriptor number */ + void *fd_ptr; /* Pointer to nfs information block */ +} fb_fdesc_t; + +typedef struct aiolist aiol_t; + +/* Functions vector for file system plug-ins */ +typedef struct fsplug_func_s { + char fs_name[16]; + int (*fsp_freemem)(fb_fdesc_t *, off64_t); + int (*fsp_open)(fb_fdesc_t *, char *, int, int); + int (*fsp_pread)(fb_fdesc_t *, caddr_t, fbint_t, off64_t); + int (*fsp_read)(fb_fdesc_t *, caddr_t, fbint_t); + int (*fsp_pwrite)(fb_fdesc_t *, caddr_t, fbint_t, off64_t); + int (*fsp_write)(fb_fdesc_t *, caddr_t, fbint_t); + int (*fsp_lseek)(fb_fdesc_t *, off64_t, int); + int (*fsp_ftrunc)(fb_fdesc_t *, off64_t); + int (*fsp_rename)(const char *, const char *); + int (*fsp_close)(fb_fdesc_t *); + int (*fsp_link)(const char *, const char *); + int (*fsp_symlink)(const char *, const char *); + int (*fsp_unlink)(char *); + ssize_t (*fsp_readlink)(const char *, char *, size_t); + int (*fsp_mkdir)(char *, int); + int (*fsp_rmdir)(char *); + DIR *(*fsp_opendir)(char *); + struct dirent *(*fsp_readdir)(DIR *); + int (*fsp_closedir)(DIR *); + int (*fsp_fsync)(fb_fdesc_t *); + int (*fsp_stat)(char *, struct stat64 *); + int (*fsp_fstat)(fb_fdesc_t *, struct stat64 *); + int (*fsp_access)(const char *, int); +} fsplug_func_t; + +extern fsplug_func_t *fs_functions_vec; + +/* Macros for calling functions */ +#define FB_FREEMEM(fd, sz) \ + (*fs_functions_vec->fsp_freemem)(fd, sz) + +#define FB_OPEN(fd, path, flags, perms) \ + (*fs_functions_vec->fsp_open)(fd, path, flags, perms) + +#define FB_PREAD(fdesc, iobuf, iosize, offset) \ + (*fs_functions_vec->fsp_pread)(fdesc, iobuf, iosize, offset) + +#define FB_READ(fdesc, iobuf, iosize) \ + (*fs_functions_vec->fsp_read)(fdesc, iobuf, iosize) + +#define FB_PWRITE(fdesc, iobuf, iosize, offset) \ + (*fs_functions_vec->fsp_pwrite)(fdesc, iobuf, iosize, offset) + +#define FB_WRITE(fdesc, iobuf, iosize) \ + (*fs_functions_vec->fsp_write)(fdesc, iobuf, iosize) + +#define FB_LSEEK(fdesc, amnt, whence) \ + (*fs_functions_vec->fsp_lseek)(fdesc, amnt, whence) + +#define FB_CLOSE(fdesc) \ + (*fs_functions_vec->fsp_close)(fdesc) + +#define FB_UNLINK(path) \ + (*fs_functions_vec->fsp_unlink)(path) + +#define FB_MKDIR(path, perm) \ + (*fs_functions_vec->fsp_mkdir)(path, perm) + +#define FB_RMDIR(path) \ + (*fs_functions_vec->fsp_rmdir)(path) + +#define FB_OPENDIR(path) \ + (*fs_functions_vec->fsp_opendir)(path) + +#define FB_READDIR(dir) \ + (*fs_functions_vec->fsp_readdir)(dir) + +#define FB_CLOSEDIR(dir) \ + (*fs_functions_vec->fsp_closedir)(dir) + +#define FB_FSYNC(fdesc) \ + (*fs_functions_vec->fsp_fsync)(fdesc) + +#define FB_STAT(path, statp) \ + (*fs_functions_vec->fsp_stat)(path, statp) + +#define FB_FSTAT(fdesc, statp) \ + (*fs_functions_vec->fsp_fstat)(fdesc, statp) + +#define FB_FTRUNC(fdesc, size) \ + (*fs_functions_vec->fsp_ftrunc)(fdesc, size) + +#define FB_LINK(existing, new) \ + (*fs_functions_vec->fsp_link)(existing, new) + +#define FB_SYMLINK(name1, name2) \ + (*fs_functions_vec->fsp_symlink)(name1, name2) + +#endif /* _FSPLUG_H */ diff --git a/usr/src/cmd/filebench/common/ipc.h b/usr/src/cmd/filebench/common/ipc.h index 8416a32ca7..cc3372cf9c 100644 --- a/usr/src/cmd/filebench/common/ipc.h +++ b/usr/src/cmd/filebench/common/ipc.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +34,7 @@ #include "fileset.h" #include "flowop.h" #include "fb_random.h" +#include "fsplug.h" #include "filebench.h" #ifdef __cplusplus @@ -186,7 +187,16 @@ typedef struct filebench_shm { caddr_t shm_addr; char *shm_ptr; - int shm_marker; /* end of pre-zeroed data */ + /* + * Type of plug-in file system client to use. Defaults to + * local file system, which is type "0". + */ + fb_plugin_type_t shm_filesys_type; + + /* + * end of pre-zeroed data + */ + int shm_marker; /* * actual storage for shared entities. diff --git a/usr/src/cmd/filebench/common/misc.c b/usr/src/cmd/filebench/common/misc.c index 553d28bcee..6f2eb4db2f 100644 --- a/usr/src/cmd/filebench/common/misc.c +++ b/usr/src/cmd/filebench/common/misc.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <stdio.h> #include <fcntl.h> #include <limits.h> @@ -36,6 +34,10 @@ #include "ipc.h" #include "eventgen.h" #include "utils.h" +#include "fsplug.h" + +/* File System functions vector */ +fsplug_func_t *fs_functions_vec; /* * Routines to access high resolution system time, initialize and @@ -43,7 +45,6 @@ * access system information strings. */ - #if !defined(sun) && defined(USE_RDTSC) /* * Lets us use the rdtsc instruction to get highres time. @@ -159,7 +160,6 @@ filebench_init(void) filebench_shutdown(1); } #endif /* USE_RDTSC */ - } extern int lex_lineno; @@ -454,3 +454,30 @@ script_var(var_t *var) return (var); } + +void fb_lfs_funcvecinit(void); + +/* + * Initialize any "plug-in" I/O function vectors. Called by each + * filebench process that is forked, as the vector is relative to + * its image. + */ +void +filebench_plugin_funcvecinit(void) +{ + + switch (filebench_shm->shm_filesys_type) { + case LOCAL_FS_PLUG: + fb_lfs_funcvecinit(); + break; + + case NFS3_PLUG: + case NFS4_PLUG: + case CIFS_PLUG: + break; + default: + filebench_log(LOG_ERROR, + "filebench_plugin_funcvecinit: unknown file system"); + break; + } +} diff --git a/usr/src/cmd/filebench/common/parser_gram.y b/usr/src/cmd/filebench/common/parser_gram.y index e3a3594c5d..bfce53b9c8 100644 --- a/usr/src/cmd/filebench/common/parser_gram.y +++ b/usr/src/cmd/filebench/common/parser_gram.y @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Portions Copyright 2008 Denis Cheng @@ -1786,6 +1786,9 @@ main(int argc, char *argv[]) exit(1); } + /* get correct function pointer for each child process */ + filebench_plugin_funcvecinit(); + if (procflow_exec(procname, instance) < 0) { filebench_log(LOG_ERROR, "Cannot startup process %s", procname); @@ -1802,6 +1805,7 @@ main(int argc, char *argv[]) if (fscriptname) (void) strcpy(filebench_shm->shm_fscriptname, fscriptname); + filebench_plugin_funcvecinit(); flowop_init(); stats_init(); eventgen_init(); @@ -2600,6 +2604,12 @@ parser_fileset_define_common(cmd_t *cmd) attr_t *attr; avd_t pathname; + /* + * Make sure all plugin flowops are initialized. + * Defaults to local fs for now + */ + flowop_plugin_flowinit(); + /* Get the name of the file */ if (attr = get_attr_fileset(cmd, FSA_NAME)) { name = attr->attr_avd; diff --git a/usr/src/cmd/filebench/common/procflow.c b/usr/src/cmd/filebench/common/procflow.c index 4fe5495363..9d124912cc 100644 --- a/usr/src/cmd/filebench/common/procflow.c +++ b/usr/src/cmd/filebench/common/procflow.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Portions Copyright 2008 Denis Cheng @@ -628,7 +628,7 @@ procflow_allstarted() void procflow_shutdown(void) { - procflow_t *procflow = filebench_shm->shm_proclist; + procflow_t *procflow; int wait_cnt; (void) ipc_mutex_lock(&filebench_shm->shm_procs_running_lock); @@ -640,6 +640,7 @@ procflow_shutdown(void) (void) ipc_mutex_unlock(&filebench_shm->shm_procs_running_lock); (void) ipc_mutex_lock(&filebench_shm->shm_procflow_lock); + procflow = filebench_shm->shm_proclist; filebench_shm->shm_f_abort = 1; wait_cnt = SHUTDOWN_WAIT_SECONDS; diff --git a/usr/src/cmd/filebench/common/threadflow.c b/usr/src/cmd/filebench/common/threadflow.c index 0d903cb367..f723cc23af 100644 --- a/usr/src/cmd/filebench/common/threadflow.c +++ b/usr/src/cmd/filebench/common/threadflow.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Portions Copyright 2008 Denis Cheng @@ -314,10 +314,11 @@ threadflow_delete(threadflow_t **threadlist, threadflow_t *threadflow, void threadflow_delete_all(threadflow_t **threadlist, int wait_cnt) { - threadflow_t *threadflow = *threadlist; + threadflow_t *threadflow; (void) ipc_mutex_lock(&filebench_shm->shm_threadflow_lock); + threadflow = *threadlist; filebench_log(LOG_DEBUG_IMPL, "Deleting all threads"); while (threadflow) { diff --git a/usr/src/cmd/filebench/common/threadflow.h b/usr/src/cmd/filebench/common/threadflow.h index 125280e816..ee08afbc2f 100644 --- a/usr/src/cmd/filebench/common/threadflow.h +++ b/usr/src/cmd/filebench/common/threadflow.h @@ -19,16 +19,15 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _FB_THREADFLOW_H #define _FB_THREADFLOW_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include "config.h" +#include "fsplug.h" #include <pthread.h> #ifndef HAVE_CADDR_T1 @@ -86,7 +85,7 @@ typedef struct threadflow { caddr_t tf_mem; /* Private Memory */ avd_t tf_memsize; /* Private Memory size attribute */ fbint_t tf_constmemsize; /* constant copy of memory size */ - int tf_fd[THREADFLOW_MAXFD + 1]; /* Thread local fd's */ + fb_fdesc_t tf_fd[THREADFLOW_MAXFD + 1]; /* Thread local fd's */ filesetentry_t *tf_fse[THREADFLOW_MAXFD + 1]; /* Thread local files */ int tf_fdrotor; /* Rotating fd within set */ flowstat_t tf_stats; /* Thread statistics */ diff --git a/usr/src/cmd/filebench/config/Makefile b/usr/src/cmd/filebench/config/Makefile index ef6541041e..fe8e43b211 100644 --- a/usr/src/cmd/filebench/config/Makefile +++ b/usr/src/cmd/filebench/config/Makefile @@ -19,7 +19,7 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -28,7 +28,8 @@ include ../../Makefile.cmd CONFIGS = fileio.prof filemacro.prof filemicro.prof generic.func \ -seqread.prof randomread.prof multi_fileserver.prof videoserver.prof +seqread.prof randomread.prof multi_fileserver.prof newfeatures.prof \ +videoserver.prof ROOTUSRBENCHDIR = $(ROOT)/usr/benchmarks ROOTUSRBENCHFBCONFIGDIR = $(ROOTUSRBENCHDIR)/filebench/config FBCONFIGS = $(CONFIGS:%=$(ROOTUSRBENCHFBCONFIGDIR)/%) diff --git a/usr/src/cmd/filebench/config/newfeatures.prof b/usr/src/cmd/filebench/config/newfeatures.prof new file mode 100644 index 0000000000..6040fc92db --- /dev/null +++ b/usr/src/cmd/filebench/config/newfeatures.prof @@ -0,0 +1,86 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# Excersizes the latest features of FileBench by running their +# respective test workloads. + +DEFAULTS { + runtime = 120; + dir = /tmp; + stats = /tmp; + filesystem = tmpfs; + description = "newfeatures tmpfs"; +} + +CONFIG seqwrite_randvar_gamma { + function = generic; + personality = filemicro_seqwriterandvargam; +} + +CONFIG seqwrite_randvar_tabular { + function = generic; + personality = filemicro_seqwriterandvartab; +} + +CONFIG list_dirs_test { + function = generic; + personality = listdirs; +} + +CONFIG make_dirs_test { + function = generic; + personality = makedirs; +} + +CONFIG remove_dirs_test { + function = generic; + personality = removedirs; +} + +CONFIG open_files_test { + function = generic; + personality = openfiles; +} + +CONFIG video_server_test { + function = generic; + personality = videoserver; + filesize = 2g; + numactivevids = 4; + numpassivevids = 20; + nthreads = 6; + srvbwrate = 12; + repintval = 20; + passvidsname = bigfileset; + actvidsname = u2fileset; +} + +CONFIG file_indexing_test { + function = generic; + personality = randomfileaccess; +} + +CONFIG composite_flowop_test { + function = generic; + personality = compflow_demo; +} diff --git a/usr/src/pkgdefs/SUNWfilebench/prototype_com b/usr/src/pkgdefs/SUNWfilebench/prototype_com index 2cb8680c29..553ff7e1ea 100644 --- a/usr/src/pkgdefs/SUNWfilebench/prototype_com +++ b/usr/src/pkgdefs/SUNWfilebench/prototype_com @@ -20,7 +20,7 @@ # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # @@ -44,6 +44,7 @@ f none usr/benchmarks/filebench/config/filemacro.prof 444 root bin f none usr/benchmarks/filebench/config/filemicro.prof 444 root bin f none usr/benchmarks/filebench/config/generic.func 444 root bin f none usr/benchmarks/filebench/config/multi_fileserver.prof 444 root bin +f none usr/benchmarks/filebench/config/newfeatures.prof 444 root bin f none usr/benchmarks/filebench/config/seqread.prof 444 root bin f none usr/benchmarks/filebench/config/randomread.prof 444 root bin f none usr/benchmarks/filebench/config/videoserver.prof 444 root bin |