--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/filebench/common/fb_localfs.c Mon Jan 26 09:32:31 2009 -0800
@@ -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));
+}
--- a/usr/src/cmd/filebench/common/flowop_library.c Sat Jan 24 16:15:58 2009 +0800
+++ b/usr/src/cmd/filebench/common/flowop_library.c Mon Jan 26 09:32:31 2009 -0800
@@ -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_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;
-
- 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);
+ int nops = sizeof (flowoplib_funcs) / sizeof (flowop_proto_t);
+
+ flowop_flow_init(flowoplib_funcs, nops);
}
/*
@@ -461,14 +386,14 @@
*/
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 @@
}
}
- *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 @@
* 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 @@
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 @@
}
(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 @@
(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 @@
(void) flowop_endop(threadflow, flowop, ret);
if ((ret == 0))
- (void) lseek64(filedesc, 0, SEEK_SET);
+ (void) FB_LSEEK(fdesc, 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;
- }
-
- 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 @@
*/
/*
- * 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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
}
/* 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 @@
/* 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 @@
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 @@
/* 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 @@
/* 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 @@
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 @@
/* 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 @@
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 @@
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 @@
{
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 @@
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 @@
}
/* 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 @@
{
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 @@
/* 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 @@
} 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 @@
{
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 @@
/* 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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
{
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 @@
}
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 @@
/* 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);
}