Make test 040 less verbose since only I need to know this; integrate some old IRIX...
authorfsgqa <fsgqa>
Wed, 3 Sep 2003 00:30:33 +0000 (00:30 +0000)
committerfsgqa <fsgqa>
Wed, 3 Sep 2003 00:30:33 +0000 (00:30 +0000)
040
040.good [new file with mode: 0644]
040.out
src/Makefile
src/dirperf.c [new file with mode: 0644]
src/metaperf.c [new file with mode: 0644]

diff --git a/040 b/040
index b865b915e710083901956b293202a6ea5a936ce9..57f67306749a089bcdb6371536a8e6f9b072c14a 100755 (executable)
--- a/040
+++ b/040
@@ -36,7 +36,7 @@
 #-----------------------------------------------------------------------
 #
 # creator
-owner=dxm@sgi.com
+owner=nathans@sgi.com
 
 seq=`basename $0`
 echo "QA output created by $seq"
@@ -74,8 +74,13 @@ then
     _notrun "Can't find XFS command headers under \"$WORKAREA\""
 fi
 
-cd $WORKAREA/cmd/xfstests/tools
-perl ./srcdiff -q
+cd $WORKAREA/cmd/xfstests
+echo Silence is golden.
+perl tools/srcdiff -q >$seq.full
+if ! diff $seq.full $seq.good >/dev/null; then
+    echo "FAILED: srcdiff output $seq.full differs to $seq.good"
+    exit 1
+fi
 
 # success, all done
 status=0
diff --git a/040.good b/040.good
new file mode 100644 (file)
index 0000000..6df7788
--- /dev/null
+++ b/040.good
@@ -0,0 +1,16 @@
+
+=== Checking attr package ===
+
+=== Checking acl package ===
+
+=== Checking dmapi package ===
+
+=== Checking xfsdump package ===
+
+=== Checking xfsprogs package ===
+
+=== Checking headers ===
+
+=== Checking libxfs code ===
+
+=== Checking libxlog code ===
diff --git a/040.out b/040.out
index f4e671f8f140354cd78bfecd83e44ec4b7bb64e5..45b1dea52f5d851ed4b07edd150d7f085c185f87 100644 (file)
--- a/040.out
+++ b/040.out
@@ -1,17 +1,2 @@
 QA output created by 040
-
-=== Checking attr package ===
-
-=== Checking acl package ===
-
-=== Checking dmapi package ===
-
-=== Checking xfsdump package ===
-
-=== Checking xfsprogs package ===
-
-=== Checking headers ===
-
-=== Checking libxfs code ===
-
-=== Checking libxlog code ===
+Silence is golden.
index 8488efeb12e43f469f9982c3556cdb46466df4ff..daa1f7367add0a9cac27f6ab5cf5e69a0c3b6eba 100644 (file)
@@ -36,7 +36,8 @@ include $(TOPDIR)/include/builddefs
 TARGETS = alloc acl_get bstat devzero dirstress fault feature \
          fill fill2 getpagesize holes xfsctl loggen lstat64 \
          nametest permname randholes runas truncfile usemem \
-         fstest mmapcat append_reader append_writer
+         fstest mmapcat append_reader append_writer \
+         dirperf metaperf
 ifeq ($(ENABLE_DBM), yes)
 TARGETS += dbtest
 endif
@@ -67,5 +68,8 @@ bstat: bstat.o $(LIBHANDLE)
 loggen:        loggen.o
        $(LINKTEST) $(LDLIBS)
 
+fstest:        fstest.o
+       $(LINKTEST)
+
 acl_get: acl_get.o $(LIBACL) $(LIBATTR)
        $(LINKTEST) $(LIBACL) $(LIBATTR) $(LDLIBS)
diff --git a/src/dirperf.c b/src/dirperf.c
new file mode 100644 (file)
index 0000000..d1159f2
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define MAXNAMELEN 256
+typedef unsigned int uint_t;
+
+/*
+ * Loop over directory sizes:
+ *     make m directories
+ *     touch n files in each directory
+ *     stat the files round-robin
+ *     readdir/unlink the files 
+ * Change directory sizes by multiplication or addition.
+ * Allow control of starting & stopping sizes, name length, target directory.
+ * Print size and wallclock time (ms per file).
+ * Output can be used to make graphs (gnuplot)
+ */
+
+static uint_t  addval;
+static uint_t  dirchars;
+static char    *dirname;
+static uint_t  firstsize;
+static uint_t  lastsize;
+static uint_t  minchars;
+static double  mulval;
+static uint_t  nchars;
+static uint_t  ndirs;
+static uint_t  pfxchars;
+static uint_t  stats;
+
+static void    filename(int, int, char *);
+static int     hexchars(uint_t);
+static uint_t  nextsize(uint_t);
+static double  now(void);
+static void    usage(void);
+
+/*
+ * Maximum size allowed, this is pretty nuts.
+ * The largest one we've ever built has been about 2 million.
+ */
+#define        MAX_DIR_SIZE    (16 * 1024 * 1024)
+#define        DFL_FIRST_SIZE  1
+#define        DFL_LAST_SIZE   (1024 * 1024)
+#define        MAX_DIR_COUNT   1024
+
+int
+main(int argc, char **argv)
+{
+       int             c;
+       uint_t          cursize;
+       DIR             *dirp;
+       int             i;
+       int             j;
+       char            name[MAXNAMELEN];
+       struct stat     stb;
+       double          stime;
+
+       while ((c = getopt(argc, argv, "a:c:d:f:l:m:n:s:")) != -1) {
+               switch (c) {
+               case 'a':
+                       addval = (uint_t)atoi(optarg);
+                       break;
+               case 'c':
+                       nchars = (uint_t)atoi(optarg);
+                       break;
+               case 'd':
+                       dirname = optarg;
+                       break;
+               case 'f':
+                       firstsize = (uint_t)atoi(optarg);
+                       break;
+               case 'l':
+                       lastsize = (uint_t)atoi(optarg);
+                       break;
+               case 'm':
+                       mulval = atof(optarg);
+                       break;
+               case 'n':
+                       ndirs = (uint_t)atoi(optarg);
+                       break;
+               case 's':
+                       stats = (uint_t)atoi(optarg);
+                       break;
+               case '?':
+               default:
+                       usage();
+                       exit(1);
+               }
+       }
+       if (!addval && !mulval)
+               mulval = 2.0;
+       else if ((addval && mulval) || mulval < 0.0) {
+               usage();
+               exit(1);
+       }
+       if (stats == 0)
+               stats = 1;
+       if (!dirname)
+               dirname = ".";
+       else {
+               if (mkdir(dirname, 0777) < 0 && errno != EEXIST) {
+                       perror(dirname);
+                       exit(1);
+               }
+               if (chdir(dirname) < 0) {
+                       perror(dirname);
+                       exit(1);
+               }
+       }
+       if (firstsize == 0)
+               firstsize = DFL_FIRST_SIZE;
+       else if (firstsize > MAX_DIR_SIZE)
+               firstsize = MAX_DIR_SIZE;
+       if (lastsize == 0)
+               lastsize = DFL_LAST_SIZE;
+       else if (lastsize > MAX_DIR_SIZE)
+               lastsize = MAX_DIR_SIZE;
+       if (lastsize < firstsize)
+               lastsize = firstsize;
+       minchars = hexchars(lastsize - 1);
+       if (nchars < minchars)
+               nchars = minchars;
+       else if (nchars >= MAXNAMELEN)
+               nchars = MAXNAMELEN - 1;
+       if (ndirs > MAX_DIR_COUNT)
+               ndirs = MAX_DIR_COUNT;
+       dirchars = hexchars(ndirs);
+       pfxchars = nchars - minchars;
+       if (pfxchars)
+               memset(&name[dirchars + 1], 'a', pfxchars);
+       for (j = 0; j < ndirs; j++) {
+               filename(0, j, name);
+               name[dirchars] = '\0';
+               mkdir(name, 0777);
+       }
+       for (cursize = firstsize;
+            cursize <= lastsize;
+            cursize = nextsize(cursize)) {
+               stime = now();
+               for (i = 0; i < cursize; i++) {
+                       for (j = 0; j < ndirs; j++) {
+                               filename((i + j) % cursize, j, name);
+                               close(creat(name, 0666));
+                       }
+               }
+               for (i = 0; i < cursize * stats; i++) {
+                       for (j = 0; j < ndirs; j++) {
+                               filename((i + j) % cursize, j, name);
+                               stat(name, &stb);
+                       }
+               }
+               for (j = 0; j < ndirs; j++) {
+                       filename(0, j, name);
+                       name[dirchars] = '\0';
+                       dirp = opendir(name);
+                       while (readdir(dirp))
+                               continue;
+                       closedir(dirp);
+               }
+               for (i = 0; i < cursize; i++) {
+                       for (j = 0; j < ndirs; j++) {
+                               filename((i + j) % cursize, j, name);
+                               unlink(name);
+                       }
+               }
+               printf("%d %.3f\n", cursize,
+                       (now() - stime) * 1.0e3 / (cursize * ndirs));
+       }
+       for (j = 0; j < ndirs; j++) {
+               filename(0, j, name);
+               name[dirchars] = '\0';
+               rmdir(name);
+       }
+       return 0;
+}
+
+static void
+filename(int idx, int dir, char *name)
+{
+       static char     hexc[16] = "0123456789abcdef";
+       int             i;
+
+       for (i = dirchars - 1; i >= 0; i--)
+               *name++ = hexc[(dir >> (4 * i)) & 0xf];
+       *name++ = '/';
+       name += pfxchars;               /* skip pfx a's */
+       for (i = minchars - 1; i >= 0; i--)
+               *name++ = hexc[(idx >> (4 * i)) & 0xf];
+       *name = '\0';
+}
+
+static int
+hexchars(uint_t maxval)
+{
+       if (maxval < 16)
+               return 1;
+       if (maxval < 16 * 16)
+               return 2;
+       if (maxval < 16 * 16 * 16)
+               return 3;
+       if (maxval < 16 * 16 * 16 * 16)
+               return 4;
+       if (maxval < 16 * 16 * 16 * 16 * 16)
+               return 5;
+       if (maxval < 16 * 16 * 16 * 16 * 16 * 16)
+               return 6;
+       if (maxval < 16 * 16 * 16 * 16 * 16 * 16 * 16)
+               return 7;
+       return 8;
+}
+
+static uint_t
+nextsize(uint_t cursize)
+{
+       double  n;
+
+       n = cursize;
+       if (addval)
+               n += addval;
+       else
+               n *= mulval;
+       if (n > (double)lastsize + 0.5)
+               return lastsize + 1;    /* i.e. out of bounds */
+       else if ((uint_t)n == cursize)
+               return cursize + 1;
+       else
+               return (uint_t)n;
+}
+
+static double
+now(void)
+{
+       struct timeval  tv;
+
+       gettimeofday(&tv, NULL);
+       return (double)tv.tv_sec + 1.0e-6 * (double)tv.tv_usec;
+}
+
+static void
+usage(void)
+{
+       fprintf(stderr,
+               "usage: dirperf [-d dir] [-a addstep | -m mulstep] [-f first] "
+               "[-l last] [-c nchars] [-n ndirs] [-s nstats]\n");
+}
diff --git a/src/metaperf.c b/src/metaperf.c
new file mode 100644 (file)
index 0000000..f4d7eaf
--- /dev/null
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * 
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ * 
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ * 
+ * http://www.sgi.com 
+ * 
+ * For further information regarding this notice, see: 
+ * 
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_GETDENTS
+#include <sys/dirent.h>
+#endif
+
+typedef        void    *(*fpi_t)(void);
+typedef        void    (*fpt_t)(int, void *);
+typedef        void    (*fpd_t)(void *);
+typedef struct tdesc
+{
+       char    *name;
+       fpi_t   init;
+       fpt_t   test;
+       fpd_t   done;
+} tdesc_t;
+
+#ifdef HAVE_GETDENTS
+static void    d_getdents(void *);
+static void    *i_getdents(void);
+static void    t_getdents(int, void *);
+#endif
+static void    crfiles(char **, int, char *);
+static void    d_chown(void *);
+static void    d_create(void *);
+static void    d_linkun(void *);
+static void    d_open(void *);
+static void    d_rename(void *);
+static void    d_stat(void *);
+static void    delflist(char **);
+static void    dotest(tdesc_t *);
+static void    *i_chown(void);
+static void    *i_create(void);
+static void    *i_linkun(void);
+static void    *i_open(void);
+static void    *i_rename(void);
+static void    *i_stat(void);
+static char    **mkflist(int, int, char);
+static double  now(void);
+static void    prtime(char *, int, double);
+static void    rmfiles(char **);
+static void    t_chown(int, void *);
+static void    t_create(int, void *);
+static void    t_crunlink(int, void *);
+static void    t_linkun(int, void *);
+static void    t_open(int, void *);
+static void    t_rename(int, void *);
+static void    t_stat(int, void *);
+static void    usage(void);
+
+tdesc_t        tests[] = {
+       { "chown",      i_chown, t_chown, d_chown },
+       { "create",     i_create, t_create, d_create },
+       { "crunlink",   (fpi_t)0, t_crunlink, (fpd_t)0 },
+#ifdef HAVE_GETDENTS
+       { "getdents",   i_getdents, t_getdents, d_getdents },
+#endif
+       { "linkun",     i_linkun, t_linkun, d_linkun },
+       { "open",       i_open, t_open, d_open },
+       { "rename",     i_rename, t_rename, d_rename },
+       { "stat",       i_stat, t_stat, d_stat },
+       { NULL }
+};
+
+char           *buffer;
+int            compact = 0;
+int            files_bg = 0;
+int            files_op = 1;
+char           **flist_bg;
+char           **flist_op;
+int            fnlen_bg = 5;
+int            fnlen_op = 5;
+int            fsize = 0;
+int            iters = 0;
+double         time_end;
+double         time_start;
+int            totsec = 0;
+int            verbose = 0;
+
+struct getdents_data
+{
+       void    *buffer;
+       int     buflen;
+       int     fd;
+};
+
+int
+main(int argc, char **argv)
+{
+       int             c;
+       char            *testdir;
+       tdesc_t         *tp;
+
+       testdir = getenv("TMPDIR");
+       if (testdir == NULL)
+               testdir = ".";
+       while ((c = getopt(argc, argv, "cd:i:l:L:n:N:s:t:v")) != -1) {
+               switch (c) {
+               case 'c':
+                       compact = 1;
+                       break;
+               case 'd':
+                       testdir = optarg;
+                       break;
+               case 'i':
+                       iters = atoi(optarg);   
+                       break;
+               case 'l':
+                       fnlen_op = atoi(optarg);
+                       break;
+               case 'L':
+                       fnlen_bg = atoi(optarg);
+                       break;
+               case 'n':
+                       files_op = atoi(optarg);
+                       break;
+               case 'N':
+                       files_bg = atoi(optarg);
+                       break;
+               case 's':
+                       fsize = atoi(optarg);
+                       break;
+               case 't':
+                       totsec = atoi(optarg);
+                       break;
+               case 'v':
+                       verbose = 1;
+                       break;
+               case '?':
+                       fprintf(stderr, "bad option\n");
+                       usage();
+               }
+       }
+       if (!iters && !totsec)
+               iters = 1;
+       if (chdir(testdir) < 0) {
+               perror(testdir);
+               return 1;
+       }
+       if (mkdir("metaperf", 0777) < 0 || chdir("metaperf") < 0) {
+               perror("metaperf");
+               return 1;
+       }
+       for (; optind < argc; optind++) {
+               for (tp = tests; tp->name; tp++) {
+                       if (strcmp(argv[optind], tp->name) == 0) {
+                               dotest(tp);
+                               break;
+                       }
+               }
+       }
+       chdir("..");
+       rmdir("metaperf");
+       return 0;
+}
+
+static void
+crfiles(char **flist, int fsize, char *buf)
+{
+       int     fd;
+       char    **fnp;
+
+       for (fnp = flist; *fnp; fnp++) {
+               fd = creat(*fnp, 0666);
+               if (fsize)
+                       write(fd, buf, fsize);
+               close(fd);
+       }
+}
+
+/* ARGSUSED */
+static void
+d_chown(void *v)
+{
+       rmfiles(flist_op);
+}
+
+/* ARGSUSED */
+static void
+d_create(void *v)
+{
+       rmfiles(flist_op);
+}
+
+#ifdef HAVE_GETDENTS
+static void
+d_getdents(void *v)
+{
+       struct getdents_data *g; 
+
+       rmfiles(flist_op);
+       g = v;
+       close(g->fd);
+       free(g->buffer);
+       free(g);
+}
+#endif
+
+/* ARGSUSED */
+static void
+d_linkun(void *v)
+{
+       unlink("a");
+}
+
+/* ARGSUSED */
+static void
+d_open(void *v)
+{
+       rmfiles(flist_op);
+}
+
+static void
+d_rename(void *v)
+{
+       rmfiles(flist_op);
+       rmfiles((char **)v);
+       delflist((char **)v);
+}
+
+/* ARGSUSED */
+static void
+d_stat(void *v)
+{
+       rmfiles(flist_op);
+}
+
+static void
+delflist(char **flist)
+{
+       char    **fnp;
+
+       for (fnp = flist; *fnp; fnp++)
+               free(*fnp);
+       free(flist);
+}
+
+static void
+dotest(tdesc_t *tp)
+{
+       double  dn;
+       double  gotsec;
+       int     n;
+       void    *v;
+
+       flist_bg = mkflist(files_bg, fnlen_bg, 'b');
+       flist_op = mkflist(files_op, fnlen_op, 'o');
+       if (fsize)
+               buffer = calloc(fsize, 1);
+       else
+               buffer = NULL;
+       crfiles(flist_bg, 0, (char *)0);
+       n = iters ? iters : 1;
+       v = (void *)0;
+       for (;;) {
+               if (tp->init)
+                       v = (tp->init)();
+               sync();
+               sleep(1);
+               time_start = now();
+               (tp->test)(n, v);
+               time_end = now();
+               if (tp->done)
+                       (tp->done)(v);
+               gotsec = time_end - time_start;
+               if (!totsec || gotsec >= 0.9 * totsec)
+                       break;
+               if (verbose)
+                       prtime(tp->name, n, gotsec);
+               if (!gotsec)
+                       gotsec = 1.0 / (2 * HZ);
+               if (gotsec < 0.001 * totsec)
+                       dn = n * (0.01 * totsec / gotsec);
+               else if (gotsec < 0.01 * totsec)
+                       dn = n * (0.1 * totsec / gotsec);
+               else
+                       dn = n * (totsec / gotsec);
+               if ((int)dn <= n)
+                       n++;
+               else
+                       n = (int)dn;
+       }
+       prtime(tp->name, n, gotsec);
+       rmfiles(flist_bg);
+       delflist(flist_bg);
+       delflist(flist_op);
+       if (fsize)
+               free(buffer);
+}
+
+static void *
+i_chown(void)
+{
+       char    **fnp;
+
+       crfiles(flist_op, 0, (char *)0);
+       for (fnp = flist_op; *fnp; fnp++)
+               chown(*fnp, 1, -1);
+       return (void *)0;
+}
+
+static void *
+i_create(void)
+{
+       crfiles(flist_op, fsize, buffer);
+       return (void *)0;
+}
+
+#ifdef HAVE_GETDENTS
+static void *
+i_getdents(void)
+{
+       struct getdents_data    *g;
+
+       crfiles(flist_op, 0, (char *)0);
+       g = malloc(sizeof(*g));
+       g->buflen = 16 * 1024;
+       g->buffer = malloc(g->buflen);
+       g->fd = open(".", O_RDONLY);
+       return g;
+}
+#endif
+
+static void *
+i_linkun(void)
+{
+       close(creat("a", 0666));
+       return (void *)0;
+}
+
+static void *
+i_open(void)
+{
+       crfiles(flist_op, 0, (char *)0);
+       return (void *)0;
+}
+
+static void *
+i_rename(void)
+{
+       crfiles(flist_op, 0, (char *)0);
+       return (void *)mkflist(files_op, fnlen_op, 'r');
+}
+
+static void *
+i_stat(void)
+{
+       crfiles(flist_op, 0, (char *)0);
+       return (void *)0;
+}
+
+static char **
+mkflist(int files, int fnlen, char start)
+{
+       int     i;
+       char    **rval;
+
+       rval = calloc(files + 1, sizeof(char *));
+       for (i = 0; i < files; i++) {
+               rval[i] = malloc(fnlen + 1);
+               sprintf(rval[i], "%0*d%c", fnlen - 1, i, start);
+       }
+       return rval;
+}
+
+static double
+now(void)
+{
+       struct timeval  t;
+
+       gettimeofday(&t, (void *)0);
+       return (double)t.tv_sec + 1.0e-6 * (double)t.tv_usec;
+}
+
+static void
+prtime(char *name, int n, double t)
+{
+       double  ops_per_sec;
+       double  usec_per_op;
+
+       ops_per_sec = (double)n * (double)files_op / t;
+       usec_per_op = t * 1.0e6 / ((double)n * (double)files_op);
+       if (compact)
+               printf("%s %d %d %d %d %d %d %f %f %f\n",
+                       name, n, files_op, fnlen_op, fsize, files_bg, fnlen_bg,
+                       t, ops_per_sec, usec_per_op);
+       else {
+               printf("%s: %d times, %d file(s) namelen %d",
+                       name, n, files_op, fnlen_op);
+               if (fsize)
+                       printf(" size %d", fsize);
+               if (files_bg)
+                       printf(", bg %d file(s) namelen %d",
+                               files_bg, fnlen_bg);
+               printf(", time = %f sec, ops/sec=%f, usec/op = %f\n",
+                       t, ops_per_sec, usec_per_op);
+       }
+}
+
+static void
+rmfiles(char **flist)
+{
+       char    **fnp;
+
+       for (fnp = flist; *fnp; fnp++)
+               unlink(*fnp);
+}
+
+/* ARGSUSED */
+static void
+t_chown(int n, void *v)
+{
+       char    **fnp;
+       int     i;
+
+       for (i = 0; i < n; i++) {
+               for (fnp = flist_op; *fnp; fnp++) {
+                       if ((i & 1) == 0)
+                               chown(*fnp, 2, -1);
+                       else
+                               chown(*fnp, 1, -1);
+               }
+       }
+}
+
+/* ARGSUSED */
+static void
+t_create(int n, void *v)
+{
+       int     i;
+
+       for (i = 0; i < n; i++)
+               crfiles(flist_op, fsize, buffer);
+}
+
+/* ARGSUSED */
+static void
+t_crunlink(int n, void *v)
+{
+       int     i;
+
+       for (i = 0; i < n; i++) {
+               crfiles(flist_op, fsize, buffer);
+               rmfiles(flist_op);
+       }
+}
+
+#ifdef HAVE_GETDENTS
+static void
+t_getdents(int n, void *v)
+{
+       int                     eof;
+       struct getdents_data    *g;
+       int                     i;
+       int                     j;
+
+       for (g = v, i = 0; i < n; i++) {
+               (void)lseek(g->fd, 0, SEEK_SET);
+               eof = 0;
+               do {
+                       j = ngetdents(g->fd, (dirent_t *)g->buffer, g->buflen,
+                               &eof);
+               } while (j > 0 && eof == 0);
+       }
+}
+#endif
+
+/* ARGSUSED */
+static void
+t_linkun(int n, void *v)
+{
+       char    **fnp;
+       int     i;
+
+       for (i = 0; i < n; i++) {
+               for (fnp = flist_op; *fnp; fnp++)
+                       link("a", *fnp);
+               rmfiles(flist_op);
+       }
+}
+
+/* ARGSUSED */
+static void
+t_open(int n, void *v)
+{
+       char            **fnp;
+       int             i;
+
+       for (i = 0; i < n; i++) {
+               for (fnp = flist_op; *fnp; fnp++)
+                       close(open(*fnp, O_RDWR));
+       }
+}
+
+static void
+t_rename(int n, void *v)
+{
+       char    **fnp;
+       int     i;
+       char    **rflist;
+       char    **rfp;
+
+       for (rflist = (char **)v, i = 0; i < n; i++) {
+               for (fnp = flist_op, rfp = rflist; *fnp; fnp++, rfp++) {
+                       if ((i & 1) == 0)
+                               rename(*fnp, *rfp);
+                       else
+                               rename(*rfp, *fnp);
+               }
+       }
+}
+
+/* ARGSUSED */
+static void
+t_stat(int n, void *v)
+{
+       char            **fnp;
+       int             i;
+       struct stat     stb;
+
+       for (i = 0; i < n; i++) {
+               for (fnp = flist_op; *fnp; fnp++)
+                       stat(*fnp, &stb);
+       }
+}
+
+static void
+usage(void)
+{
+       fprintf(stderr,
+               "usage: metaperf [-d dname] [-i iters|-t seconds] [-s fsize]\n\t[-l opfnamelen] [-L bgfnamelen]\n\t[-n opfcount] [-N bgfcount] test...\n");
+       fprintf(stderr,
+               "tests available: chown, create, crunlink, linkun, open, rename, stat\n");
+       exit(1);
+}